2019 CCPC - 网络选拔赛 B array(线段树)

array

Time Limit: 2000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 97    Accepted Submission(s): 22


 

Problem Description

You are given an array a1,a2,...,an(∀i∈[1,n],1≤ai≤n). Initially, each element of the array is **unique**.

Moreover, there are m instructions.

Each instruction is in one of the following two formats:

1. (1,pos),indicating to change the value of apos to apos+10,000,000;
2. (2,r,k),indicating to ask the minimum value which is **not equal** to any ai ( 1≤i≤r ) and **not less ** than k.

Please print all results of the instructions in format 2.

 

 

 

Input

The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.

In each test case, there are two integers n(1≤n≤100,000),m(1≤m≤100,000) in the first line, denoting the size of array a and the number of instructions.

In the second line, there are n distinct integers a1,a2,...,an (∀i∈[1,n],1≤ai≤n),denoting the array.
For the following m lines, each line is of format (1,t1) or (2,t2,t3).
The parameters of each instruction are generated by such way :

For instructions in format 1 , we defined pos=t1⊕LastAns . (It is promised that 1≤pos≤n)

For instructions in format 2 , we defined r=t2⊕LastAns,k=t3⊕LastAns. (It is promised that 1≤r≤n,1≤k≤n )

(Note that ⊕ means the bitwise XOR operator. )

Before the first instruction of each test case, LastAns is equal to 0 .After each instruction in format 2, LastAns will be changed to the result of that instruction.

(∑n≤510,000,∑m≤510,000 )

 

 

Output

For each instruction in format 2, output the answer in one line.

 

 

Sample Input

 

3 5 9 4 3 1 2 5 2 1 1 2 2 2 2 6 7 2 1 3 2 6 3 2 0 4 1 5 2 3 7 2 4 3 10 6 1 2 4 6 3 5 9 10 7 8 2 7 2 1 2 2 0 5 2 11 10 1 3 2 3 2 10 10 9 7 5 3 4 10 6 2 1 8 1 10 2 8 9 1 12 2 15 15 1 12 2 1 3 1 9 1 12 2 2 2 1 9

 

 

Sample Output

 

1 5 2 2 5 6 1 6 7 3 11 10 11 4 8 11

        线段树,各个点代表的是某个数,l==r时点上值代表的是这个数所在的位置在哪里,线段树维护区间最大值。

        这样我们要找到(1,r)范围内比k大的第一个未出现过的数,其实就是找比K大的数中第一个值比r 大的就行了。

#include
using namespace std;
const int M = 100010;
const int N = 100003;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int c[N * 8];
int n, m;
void pushup(int rt) {
	c[rt] = max(c[rt << 1], c[rt << 1 | 1]);
}
void build(int l, int r, int rt) {
	c[rt] = N;
	if (l == r) {
		return;
	}
	int m = (l + r) >> 1;
	build(lson);build(rson);
}
void update(int l, int r, int rt,int pos,int val) {
	if (l == r) {
		c[rt] = val;	
		return;
	}
	int m = (l + r) >> 1;
	if (pos<=m) update(lson, pos, val);
	else update(rson, pos, val);
	pushup(rt);
}
int ans = -1;
void query(int l, int r, int rt, int k, int val) {
	if (ans != -1)return;
	if (l == r) {
		//cout << l << " ??? " << c[rt] << " " << val << "\n";
		if (c[rt] > val)
			ans = l;
		return;
	}
	int m = (l + r) >> 1;
	if (m >= k && c[rt << 1] > val) 
		query(lson, k, val);
	if (c[rt << 1 | 1] > val) 
		query(rson, k, val);
	return;
}
int pos[N];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int te;
	cin >> te;
	while (te--) {
		cin >> n >> m;
		build(1, N, 1);
		memset(pos, -1, sizeof pos);
		for (int i = 1; i <= n; i++) {
			int a; cin >> a;
			pos[i] = a;
			update(1, N, 1, a, i);
		}
		int lastans = 0;
		while (m--) {
			int a, b;
			cin >> a >> b;
			if (a == 1) {
				b ^= lastans;
			//	cout << "now: " << b << "\n";
				if (pos[b] <= 100000)
					update(1, N, 1, pos[b], N);
			}
			else {
				ans = -1;
				int c; cin >> c;
				b ^= lastans; c ^= lastans;
				query(1, N, 1, c, b);
			//	cout << b << " now " << c << "\n";
				cout << ans << "\n";
				lastans = ans;
			}
		}
	}
	return 0;
}

 

你可能感兴趣的:(数据结构)