P6617 find Search

Title Link: P6617 find Search

General meaning

Given length is n n An integer sequence of n, a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1, a2,..., an. There are m operations:

pos val means to a p o s a_{pos} apos # changed to v a l val val.

l r inquiry [ l , r ] [l, r] [l,r] interval, does it exist a i + a j = w , ( i ≠ j ) a_i + a_j = w, (i \ne j) ai​+aj​=w,(i​=j).

Problem solving ideas

thinking

We consider that if there is no modification operation, we ask whether there are two numbers in different positions in an interval at a time w w w. Then we can record the position index of the first qualified number in front of each position, and then judge the maximum value of the interval i n d e x i index_i indexi # is it satisfied i n d e x i ≥ l index_i \ge l indexi ≥ l

Binding will be used to refer to two qualified positions below

Considering the modification operation, we can no longer maintain information in the above way

Let w = x + y and assume that the sequence is x, y, y, y,..., y

In this way, when we modify the first position, we need to modify all subsequent positions. Obviously, it can be stuck O ( n 2 ) O(n^2) The complexity of O(n2) is

The element of each position is only recorded by the nearest element behind it

set up w = x + y w = x + y w=x+y. considering that for the sequence a = { x , y , y , y } a = \{ x, y, y, y \} For a={x,y,y,y}, we only need to bind 1 and 2 positions

There should be no intersection between position intervals recorded by the same element

set up w = x + y w = x + y w=x+y. considering that for the sequence a = { x , x , y , y } a = \{ x, x, y, y \} For a={x,x,y,y}, we just need to bind the 2 and 3 positions

Through the above two conclusions, we find that the numbers bound forward and backward for each position can be uniquely determined. Therefore, when modifying a position, we can remove / add the impact of the current position through constant operations

Segment tree

We find that the essence of query is to query the maximum value of interval, so we can use segment tree to maintain the maximum value dynamically

For the modification operation, we can maintain the precursor and successor (binding) of each location

AC code

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 5E5 + 10;

int w[N];
struct node { //Segment tree dynamic maintenance interval maximum
	int l, r;
	int fmax;
}t[N << 2];
void pushup(int x) { t[x].fmax = max(t[x << 1].fmax, t[x << 1 | 1].fmax); }

void build(int l, int r, int x = 1) {
	t[x] = { l, r, 0 };
	if (l == r) return;
	int mid = l + r >> 1;
	build(l, mid, x << 1), build(mid + 1, r, x << 1 | 1);
}

void modify(int a, int c, int x = 1) {
	if (t[x].l == t[x].r) {
		t[x].fmax = c;
		return;
	}
	int mid = t[x].l + t[x].r >> 1;
	modify(a, c, x << 1 | (a > mid));
	pushup(x);
}

int ask(int l, int r, int x = 1) {
	if (l <= t[x].l and r >= t[x].r) return t[x].fmax;
	int mid = t[x].l + t[x].r >> 1;
	int res = 0;
	if (l <= mid) res = ask(l, r, x << 1);
	if (r > mid) res = max(res, ask(l, r, x << 1 | 1));
	return res;
}

set<int> st[N]; //Maintain where each value appears
int getnext(int x, int pos) { //Find strict successors
	auto it = st[x].upper_bound(pos);
	if (it == st[x].end()) return 0;
	return *it;
}
int getprev(int x, int pos) { //Find strict precursors
	auto it = st[x].lower_bound(pos);
	if (it == st[x].begin()) return 0;
	return *--it;
}
int link[N];
int main()
{
	int n, m, W; cin >> n >> m >> W;
	build(1, n);
	rep(i, n) {
		scanf("%d", &w[i]);
		int other = W - w[i];
		if (!st[other].empty()) { //Prevent = = W/2
			int qaq = *st[other].rbegin(); //Element position to pair
			if (!link[qaq]) link[qaq] = i, modify(i, qaq);
		}
		st[w[i]].insert(i);
	}

	int cou = 0;
	rep(i, m) {
		int tp; scanf("%d", &tp);
		if (tp == 1) {
			int a, c; scanf("%d %d", &a, &c);
			if (c == w[a]) continue;

			int posprev = ask(a, a);
			if (posprev) { //There's something ahead
				int posnext = getnext(w[a], a);
				if (posnext and !ask(posnext, posnext)) { //There is something behind and no link
					link[posprev] = posnext;
					modify(posnext, posprev);
				}
				else link[posprev] = 0;
				modify(a, 0);
			}

			if (link[a]) { //Have been link ed
				posprev = getprev(w[a], a); // Previous position

				if (posprev and !link[posprev]) { //The location is not link ed
					modify(link[a], posprev);
					link[posprev] = link[a];
				}
				else modify(link[a], 0);
				link[a] = 0;
			}


			st[w[a]].erase(a);
			w[a] = c;
			st[w[a]].insert(a);


			posprev = getprev(W - w[a], a);
			if (posprev) {
				if (link[posprev] > a) { // posprev  a  link[posprev]
					modify(link[posprev], 0);
					link[posprev] = a;
					modify(a, posprev);
				}
				else if (!link[posprev]) {
					link[posprev] = a;
					modify(a, posprev);
				}
			}


			int posnext = getnext(W - w[a], a);
			if (posnext) {
				posprev = ask(posnext, posnext);

				if (posprev < a) {  // posprev(0)   a   posnext
					link[posprev] = 0;
					modify(posnext, a);
					link[a] = posnext;
				}
			}
		}
		else {
			int l, r; scanf("%d %d", &l, &r);
			l ^= cou, r ^= cou;

			int now = ask(l, r);
			if (now >= l) cou++, puts("Yes");
			else puts("No");
		}
	}
    
	return 0;
}

END

Tags: C++ Algorithm data structure ICPC

Posted on Thu, 09 Sep 2021 14:38:05 -0400 by padma