• hdoj6703 2019 CCPC网络选拔赛 1002 array


    题意

    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 )

    ## 分析 题目中,共有两种操作,一种是将第k个数字+1000,0000,一种是求一个最小的、不等于ai(1 <= i <= r)的,且不小于k的数字。 > 注意 这个数字,可以不出现在array中

    因为array中的数字各不相同,因此,不等于ai(1 <= i <= r),等价于 这个数字可能会出现在 ai(r + 1 <= i <= n)。
    为什么是可能?因为由于第一种操作+1000,10000,会使得进行第一种操作的那个数字,无论如何都不会和ai重复(1000,0000 比 51,0000大太多了)。
    所以,这个题,我们可以将主席树进行适当的修改,每次查找ai[r + 1, n]中,不小于k的最小数字。
    由于本题中,array由1-n的n个数字组成,因此不用考虑数字的去重(unique),以及 离散化问题。
    除了上面两种情况,还有一种情况,我们没考虑到,如果k = n (已经过异或运算),那么这个答案还有可能是 n + 1。
    综上,答案一共有三种情况:

    • ai[r + 1, n] 中的某个数字 (可以用主席树求解)
    • 进行过第一种操作的某个数字 (将进行过第一种操作的数字放入set中)
    • n + 1

    三个数字,求最小值即可

    代码

    #include <iostream>
    #include <cstdio>
    #include <set>
    #include <algorithm>
    int const maxn = 530000;
    int const inf = 0x3f3f3f3f;
    using namespace std;
    int a[maxn], b[maxn];
    int root[maxn << 5];//第几个版本的根节点编号
    int lc[maxn << 5], rc[maxn << 5], sum[maxn << 5];
    int sz;//节点个数
    int n, m;
    
    void build(int &rt, int l, int r) {
    	rt = ++sz;
    	if (l == r)	return;
    	int mid = (l + r) >> 1;
    	build(lc[rt], l, mid);
    	build(rc[rt], mid + 1, r);
    }
    
    int update(int id, int l, int r, int pos) {
    	int _id = ++sz;
    	lc[_id] = lc[id], rc[_id] = rc[id], sum[_id] = sum[id] + 1;
    	if (l == r)	return _id;
    	int mid = (r + l) >> 1;
    	if (pos <= mid)
    		lc[_id] = update(lc[id], l, mid, pos);
    	else
    		rc[_id] = update(rc[id], mid + 1, r, pos);
    	return _id;
    }
    
    //查询 不比k大的最小数字
    int query(int p, int q, int l, int r, int k) {
    	if (l == r)	return l;
    	int x1 = sum[lc[q]] - sum[lc[p]];
    	int x2 = sum[rc[q]] - sum[rc[p]];
    	int mid = (l + r) >> 1;
    	int ans = inf;
    	if (x1 > 0 && mid >= k)
    		ans = query(lc[p], lc[q], l, mid, k);
    	//这个if不能写为else,因为第一个if可能无法得到结果,返回inf
    	if(ans == inf && x2 > 0 && r >= k)
    		ans = query(rc[p], rc[q], mid + 1, r, k);
    	return ans;
    }
    
    
    int main() {
    	int T;
    	scanf("%d", &T);
    	while (T--) {
    		while (~scanf("%d %d", &n, &m)) {
    			sz = 0;
    			set<int> s;
    			int lastAns = 0;
    			for (int i = 1; i <= n; i++) {
    				scanf("%d", &a[i]);
    				b[i] = a[i];
    			}
    			sort(b + 1, b + n + 1);
    			build(root[0], 1, n);
    			for (int i = 1; i <= n; i++) {
    				int pos = lower_bound(b + 1, b + n + 1, a[i]) - b;
    				root[i] = update(root[i - 1], 1, n, pos);
    			}
    			while (m--) {
    				int l;
    				scanf("%d", &l);
    				if (l == 1) {
    					int pos = 1; // 随意初始化
    					scanf("%d", &pos);
    					pos ^= lastAns;
    					//cout << "pos = " << pos << endl;
    					s.insert(a[pos]);
    				}
    				else {
    					int l, k;
    					scanf("%d %d", &l, &k);
    					l ^= lastAns;
    					k ^= lastAns;
    					//cout << "l = " << l << "k = " << k << endl;
    					int ansPos = query(root[l - 1 + 1], root[n], 1, n, k);
    					lastAns = (ansPos == inf) ? inf : b[ansPos];
    					set<int>::iterator it = s.lower_bound(k);
    					//
    					if (it != s.end())	lastAns = min(lastAns, *it);
    					lastAns = min(lastAns, n + 1);
    					printf("%d
    ", lastAns);
    				}
    			}
    		}
    	}
    	return 0;
    
  • 相关阅读:
    2.6
    zuoye
    练习1
    练习
    练习
    4
    3
    2
    1
    1.3
  • 原文地址:https://www.cnblogs.com/woxiaosade/p/11422266.html
Copyright © 2020-2023  润新知