Codeforces 703D

Problem

For a sequence of N numbers, there are M queries. Every time you ask the interval of a[l ~ r], the XOR sum of the numbers with an even number of occurrences (the numbers that do not appear are not counted).

Solution

Since it is a static interval processing, I first think of Team Mo. But the data volume of 1e6, obviously N*sqrt(N) is already 1e9.

Then I had a heated discussion with my teammates.


I, a bit-manipulating konjac, obviously didn't expect this property. Thanks to my resourceful teammates. So I was inspired! !



As shown. In the end I got stuck on how to get even numbers.



emmm, how to demultiplex XOR.....what a question.


In the end, after the stalemate reached more than 9 o'clock, we decided to write about Team Mo.

In the end, tle, who lived up to expectations, was at the 14th point. (My teammates heard about t, so they didn't write it down [rolling eyes])

#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
#define N 1000010
using namespace std;
map<int, int>mp;
struct node {int l, r, id;}que[N];
int n, a[N], m, blank, num[N], temp[N], ans1[N];
inline bool mycmp(node x, node y) {
	if(x.l/blank == y.l/blank) return (x.l/blank % 2 == 0)?x.r<y.r:x.r>y.r;
	return x.l < y.l;
}
inline char gc() {
	static char now[1<<16], *S, *T;
	if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
	return *S++;
}
inline int read() {
	int x = 0; char ch = gc();
	while(ch < '0' || ch > '9') ch = gc();
	while(ch >= '0' && ch <= '9') {x = x * 10 + ch - 48; ch = gc();}
	return x;
}
inline void print(int x) {
	if(!x) {putchar('0'); puts(""); return ;}
	int prt[30], now = 0;
	while(x) {prt[++now] = x % 10; x/= 10;}
	for(int i = now; i >= 1; --i) putchar('0' + prt[i]); puts("");
}
int main() {
	n = read(); blank = (int)sqrt(n); if(blank * blank < n) ++blank;
	for(int i = 1; i <= n; ++i) a[i] = read();
	m = read();
	for(int i = 1; i <= m; ++i) {que[i].l = read(); que[i].r = read(); que[i].id = i;}
	sort(que+1, que+m+1, mycmp);
	memcpy(temp, a, sizeof(temp)); sort(temp+1, temp+n+1); int cnt = unique(temp+1, temp+n+1) - temp - 1;
	memset(num, 0, sizeof(num)); for(int i = 1; i <= cnt; ++i) mp[temp[i]] = i;
	int lcur = 1, rcur = 0; int years = 0;
	for(int i = 1; i <= m; ++i) {
		if (lcur <que [i] .l) {
			for(int j = que[i].l - 1; j >= lcur; --j) {
				--num [mp [a [j]]];
				if(num[mp[a[j]]] > 0) ans^= a[j];
			}
			lcur = that [i] .l;
		}
		if(lcur > that[i].l) {
			for(int j = lcur - 1; j >= que[i].l; --j) {
				++ num [mp [a [j]]];
				if(num[mp[a[j]]] > 1) ans^= a[j];
			}
			lcur = that [i] .l;
		}
		if(rcur < que[i].r) {
			for(int j = rcur + 1; j <= que[i].r; ++j) {
				++ num [mp [a [j]]];
				if(num[mp[a[j]]] > 1) ans^= a[j];
			}
			rcur = que [i] .r;
		}
		if(rcur > que[i].r) {
			for(int j = que[i].r + 1; j <= rcur; ++j) {
				--num [mp [a [j]]];
				if(num[mp[a[j]]] > 0) ans^= a[j];
			}
			rcur = que [i] .r;
		}
		ans1[que[i].id] = ans;
	}
	for(int i = 1; i <= m; ++i) print(ans1[i]);
	return 0;
}

With doubts I fell asleep.

Thinking about it the next morning, we can sort by the right endpoint of the operation, and we just need to maintain the deduplicated XOR of a[1~query[i].r]. If we encounter a duplicate, change the previous position to 0 and add this number to the new position. Because your future inquiries are all covering the right side of the interval, it makes no difference whether it appears on the far left (more generally speaking, if you ask the interval where the zeroed point is located, there will be less XOR). on this number. So we made the right endpoint monotonically increasing to avoid this problem). This point operation interval query can be solved by using a tree array. So how do you remember if it happened before? We discretize the value, and then denote last[i] as the position where the value mapped to i last appeared, which can be solved.

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#define N 1000010
using namespace std;
map<int, int>mp;
int n, a[N], sum[N], m, bit[N], last[N], ans[N];
struct node {int l, r, id;}que[N];
inline bool cmp1(node xx, node yy) {return xx.r < yy.r;}
inline char gc() {
	static char now[1<<16], *S, *T;
	if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
	return *S++;
}
inline int read() {
	int x = 0; char ch = gc();
	while(ch < '0' || ch > '9') ch = gc();
	while(ch >= '0' && ch <= '9') {x = x * 10 + ch - 48; ch = gc();}
	return x;
}
inline void print(int x) {
	if(!x) {putchar('0'); puts(""); return ;}
	int prt[30], now = 0;
	while(x) {prt[++now] = x % 10; x/= 10;}
	for(int i = now; i >= 1; --i) putchar('0' + prt[i]); puts("");
}
inline void add(int p, int x) {for(int i = p; i <= n; i+= i & -i) bit[i]^= x;}
inline int query(int p) {
	int ret = 0;
	for(int i = p; i > 0; i-= i & -i) ret^= bit[i];
	return ret;
}
int main() {
	n = read();
	for(int i = 1; i <= n; ++i) {a[i] = read(); if(!mp[a[i]]) mp[a[i]] = i;}
	sum[0] = 0; for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] ^ a[i];
	m = read();
	for(int i = 1; i <= m; ++i) {que[i].l = read(); que[i].r = read(); que[i].id = i;}
	sort(que+1, que+m+1, cmp1);
	memset(bit, 0, sizeof(bit)); int p = 0; memset(last, 0, sizeof(last));
	for(int i = 1; i <= m; ++i) {
		for(int j = p + 1; j <= que[i].r; ++j) {
			if(last[mp[a[j]]]) add(last[mp[a[j]]], a[j]);
			add(j, a[j]);
			last[mp[a[j]]] = j;
		} p = that [i] .r;
		ans [que [i] .id] = (sum [que [i] .r] ^ sum [que [i] .l - 1]) ^ (query (que [i] .r) ^ query (que [i ] .l - 1));
	}
	for(int i = 1; i <= m; ++i) print(ans[i]);
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325836071&siteId=291194637