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;
}

  

posted @ 2015-09-29 22:44  Claris  阅读(781)  评论(0编辑  收藏  举报