2019CCPC网络赛——array(权值线段树)
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6703
题目大意:
给出一个n(n<1e5)个元素的数组A,A中所有元素都是不重复的[1,n]。
有两种操作:
1.将pos位置的元素+1e7
2.查询不属于[1,r]中的最小的>=k的值。
强制在线,上次计算结果和输入值xor得到区间。
比赛的时候感觉这道题有点线段树的感觉,和前段时间多校训练一个题很像,想了40多分钟才理想清思路。
解法:
可以看出,执行1操作的时候加的数非常大,可以得出每次输出的答案在为1到n+1之间。可以将1-n的每个数在数组A中的位置记录下,存在线段树中,维护线段树区间最大值。
当执行2操作时,只需要查询区间[k,n]中大于r的值即可,找出最小的数字,先搜索左子树,若无答案搜索右子树,若两侧均无解则答案为n+1。
当执行1操作时,由于pos+1e7,因此之后的数组中不存在该数,将第pos位的数字在线段树中的值转换为inf即可。
贴上自己比赛时打了40多分钟的代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; typedef pair <int,int> pii; #define rep(i,x,y) for(int i=x;i<y;i++) #define rept(i,x,y) for(int i=x;i<=y;i++) #define per(i,x,y) for(int i=x;i>=y;i--) #define pb push_back #define mp make_pair #define fi first #define se second #define de(x) cout<< #x<<" = "<<x<<endl #define dd(x) cout<< #x<<" = "<<x<<" " #define mes(a,b) memset(a,b,sizeof a) const int inf= 0x3f3f3f3f; int arrcy[100005],p[100005]; class Tree { public: int l,r,val; }tree[400005]; void build(int id,int l,int r); void change(int id,int x); void test(); int main() { ios::sync_with_stdio(false); cin.tie(0); int t; cin>>t; while(t--) test(); return 0; } int find(int id,int r,int k); void test() { int n,q; int ans=0; cin>>n>>q; rept(i,1,n) { cin>>arrcy[i]; p[arrcy[i]]=i; } build(1,1,n); rep(i,0,q) { int way; cin>>way; if(way==1) { int pos; cin>>pos; change(1,arrcy[ans^pos]); } else { int r,k; cin>>r>>k; r^=ans; k^=ans; // cout<<"r="<<r<<" "<<"k="<<k<<endl; ans=find(1,r,k); if(ans==-1) ans=max(n+1,k); cout<<ans<<endl; } } } void build(int id,int l,int r) { tree[id].l=l; tree[id].r=r; if(l==r) { tree[id].val=p[l]; return ; } int mid=(l+r)/2; build(id*2,l,mid); build(id*2+1,mid+1,r); tree[id].val=max(tree[id*2].val,tree[id*2+1].val); } int find(int id,int r,int k) { if(tree[id].l==tree[id].r) { if(tree[id].val>r) return tree[id].l; else return -1; } int mid=(tree[id].l+tree[id].r)/2,ans=-1; if(mid>=k&&tree[id*2].val>r) ans=find(id*2,r,k); if(ans!=-1) return ans; else if(tree[id*2+1].r>=k&&tree[id*2+1].val>r) ans=find(id*2+1,r,k); return ans; } void change(int id,int x)//将x转换为inf { if(tree[id].l==tree[id].r) { tree[id].val=inf; return ; } if(x<=(tree[id].l+tree[id].r)/2) change(id*2,x); else change(id*2+1,x); tree[id].val=max(tree[id*2].val,tree[id*2+1].val); }