BZOJ4137 : [FJOI2015]火星商店问题
把时间看成第一维,编号看成第二维,则每个询问等价于询问某个矩形范围内与某个数异或的最大值。
从高位到低位贪心,考虑离线分治,假设当前处理第k位,那么把所有点以及按这一位分成两类,分别扫描线+树状数组维护即可。
时间复杂度$O(n\log^2n)$。
#include<cstdio> #include<algorithm> #define N 200010 using std::sort; int n,m,cb,cq,i,j,op,x,y,z,d,tmp[N],ans[N]; struct P{int v,x,y;P(){}P(int _v,int _x,int _y){v=_v,x=_x,y=_y;}}a[N],b[N],q[N]; struct Q{int v,a,b,c,d,p;Q(){}Q(int _v,int _a,int _b,int _c,int _d,int _p){v=_v,a=_a,b=_b,c=_c,d=_d,p=_p;}}c[N],qc[N]; int ca0,ca1,a0[N],a1[N],cc0,cc1,cb0,cb1,T,bit[N],v[N]; struct QI{int x,t,p;QI(){}QI(int _x,int _t,int _p){x=_x,t=_t,p=_p;}}c0[N],c1[N]; inline bool cmpQI(const QI&a,const QI&b){return a.x<b.x;} struct B{int x,y;B(){}B(int _x,int _y){x=_x,y=_y;}}b0[N],b1[N]; inline bool cmpB(const B&a,const B&b){return a.x<b.x;} struct C{int x,l,r,t,p;C(){}C(int _x,int _l,int _r,int _t,int _p){x=_x,l=_l,r=_r,t=_t,p=_p;}}C0[N],C1[N]; inline bool cmpC(const C&a,const C&b){return a.x<b.x;} inline void add(int x){for(;x<=n;x+=x&-x)if(v[x]<T)v[x]=T,bit[x]=1;else bit[x]++;} inline int ask(int x){int t=0;for(;x;x-=x&-x)if(v[x]==T)t+=bit[x];return t;} void solve(int K,int al,int ar,int bl,int br,int cl,int cr){ if(K<0||cl>cr)return; int i,j; for(ca0=ca1=0,i=al;i<=ar;i++)if(a[i].v>>K&1)a1[ca1++]=a[i].y;else a0[ca0++]=a[i].y; for(cc0=cc1=0,i=cl;i<=cr;i++){ tmp[i]=0; if(c[i].v>>K&1)c0[cc0++]=QI(c[i].c-1,-1,i),c0[cc0++]=QI(c[i].d,1,i); else c1[cc1++]=QI(c[i].c-1,-1,i),c1[cc1++]=QI(c[i].d,1,i); } if(ca0>1)sort(a0,a0+ca0); if(cc0>1)sort(c0,c0+cc0,cmpQI); for(i=j=0;i<cc0;i++){ while(j<ca0&&a0[j]<=c0[i].x)j++; tmp[c0[i].p]+=c0[i].t*j; } if(ca1>1)sort(a1,a1+ca1); if(cc1>1)sort(c1,c1+cc1,cmpQI); for(i=j=0;i<cc1;i++){ while(j<ca1&&a1[j]<=c1[i].x)j++; tmp[c1[i].p]+=c1[i].t*j; } for(cb0=cb1=0,i=bl;i<=br;i++)if(b[i].v>>K&1)b1[cb1++]=B(b[i].x,b[i].y);else b0[cb0++]=B(b[i].x,b[i].y); for(cc0=cc1=0,i=cl;i<=cr;i++){ if(c[i].v>>K&1)C0[cc0++]=C(c[i].a-1,c[i].c,c[i].d,-1,i),C0[cc0++]=C(c[i].b,c[i].c,c[i].d,1,i); else C1[cc1++]=C(c[i].a-1,c[i].c,c[i].d,-1,i),C1[cc1++]=C(c[i].b,c[i].c,c[i].d,1,i); } if(cb0>1)sort(b0,b0+cb0,cmpB); if(cc0>1)sort(C0,C0+cc0,cmpC); for(T++,i=j=0;i<cc0;i++){ while(j<cb0&&b0[j].x<=C0[i].x)add(b0[j++].y); tmp[C0[i].p]+=C0[i].t*(ask(C0[i].r)-ask(C0[i].l-1)); } if(cb1>1)sort(b1,b1+cb1,cmpB); if(cc1>1)sort(C1,C1+cc1,cmpC); for(T++,i=j=0;i<cc1;i++){ while(j<cb1&&b1[j].x<=C1[i].x)add(b1[j++].y); tmp[C1[i].p]+=C1[i].t*(ask(C1[i].r)-ask(C1[i].l-1)); } int aL=al,aR=ar,bL=bl,bR=br,cL=cl,cR=cr; for(i=al;i<=ar;i++)if(a[i].v>>K&1)q[aL++]=a[i];else q[aR--]=a[i]; for(i=al;i<=ar;i++)a[i]=q[i]; for(i=bl;i<=br;i++)if(b[i].v>>K&1)q[bL++]=b[i];else q[bR--]=b[i]; for(i=bl;i<=br;i++)b[i]=q[i]; for(i=cl;i<=cr;i++){ if(tmp[i])ans[c[i].p]|=1<<K; if((tmp[i]>0)^(c[i].v>>K&1))qc[cL++]=c[i];else qc[cR--]=c[i]; } for(i=cl;i<=cr;i++)c[i]=qc[i]; solve(K-1,al,aR,bl,bR,cl,cR),solve(K-1,aR+1,ar,bR+1,br,cR+1,cr); } inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int main(){ for(read(n),read(m),i=1;i<=n;i++)read(x),a[i]=P(x,0,i),j=j>x?j:x; while(m--){ read(op),read(x),read(y); if(op)read(z),read(d),c[++cq]=Q(z,cb-d+1,cb,x,y,cq),j=j>z?j:z;else b[++cb]=P(y,cb,x),j=j>y?j:y; } for(i=0;1<<i<j;i++); for(solve(i,1,n,1,cb,1,cq),i=1;i<=cq;i++)printf("%d\n",ans[i]); return 0; }