BZOJ4571:[SCOI2016]美味
阿新 • • 發佈:2018-11-17
algorithm 時間復雜度 getchar 題目 當前 pro com tps 直接
淺談主席樹:https://www.cnblogs.com/AKMer/p/9956734.html
題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=4571
直接從高位到低位貪心。我們可以一位一位確定還沒與\(b\)異或起來的\(ans\),最後再與\(b\)異或。假設前面的高位確定完之後,根據當前位貪心需要什麽,可以在一段區間內找到我們需要的數字。如果存在,那麽這一位就是貪心的結果,否則就是另一種。在一段區間內找值域在某一段區間的數字,正好可以用主席樹搞定。
時間復雜度:\(O(nlognlogv)\)
空間復雜度:\(O(nlogv)\)
代碼如下:
#include <cstdio> #include <algorithm> using namespace std; const int maxn=2e5+5; int n,m; int rt[maxn]; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct tree_node { int cnt,ls,rs; }; struct chairman_tree { int tot; tree_node tree[maxn*18]; void ins(int lst,int &now,int l,int r,int pos) { now=++tot;tree[now]=tree[lst]; tree[now].cnt++; if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)ins(tree[lst].ls,tree[now].ls,l,mid,pos); else ins(tree[lst].rs,tree[now].rs,mid+1,r,pos); } int query(int x,int y,int l,int r,int L,int R) { if(L<=l&&r<=R)return tree[y].cnt-tree[x].cnt; int mid=(l+r)>>1,res=0; if(L<=mid)res+=query(tree[x].ls,tree[y].ls,l,mid,L,R); if(R>mid)res+=query(tree[x].rs,tree[y].rs,mid+1,r,L,R); return res; } }T; int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { int x=read(); T.ins(rt[i-1],rt[i],0,1e5,x); } for(int i=1;i<=m;i++) { int b=read(),x=read(),l=read(),r=read(),ans=0; for(int j=17;~j;j--) { int L,R,bit; if(b&(1<<j))L=ans,R=ans+(1<<j)-1,bit=0; else L=ans+(1<<j),R=ans+(1<<(j+1))-1,bit=1; L=max(L-x,0);R=min(100000,R-x); bool bo=T.query(rt[l-1],rt[r],0,1e5,L,R); if(!bo)bit^=1;ans|=bit<<j; }ans^=b; printf("%d\n",ans); } return 0; }
BZOJ4571:[SCOI2016]美味