1 条题解

  • 0
    @ 2025-10-8 17:10:47

    C59 可持久化线段树+异或+贪心 P3293 [SCOI2016] 美味

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    void read(int &x){ //快读
      x=0; char c=getchar();
      while(!isdigit(c))c=getchar();
      while(isdigit(c))x=x*10+c-'0',c=getchar();
    }
    const int N=200005;
    #define mid ((l+r)>>1)
    int n,m,mx,a[N];
    int root[N],tot; //根节点,开点个数
    int ls[N*25],rs[N*25],sum[N*25];
    //sum:区间值的个数的前缀和
    
    void change(int &u,int v,int l,int r,int p){ //点修
      u=++tot;
      ls[u]=ls[v]; rs[u]=rs[v]; sum[u]=sum[v]+1;
      if(l==r) return;
      if(p<=mid) change(ls[u],ls[v],l,mid,p);
      else change(rs[u],rs[v],mid+1,r,p);
    }
    int query(int u,int v,int l,int r,int x,int y){ //区查
      if(y<l||x>r) return 0;
      if(x<=l&&r<=y) return sum[u]-sum[v];
      return query(ls[u],ls[v],l,mid,x,y)
            +query(rs[u],rs[v],mid+1,r,x,y);
    }
    int main(){
      read(n);read(m);
      for(int i=1;i<=n;i++)
        read(a[i]),mx=max(a[i],mx);
      for(int i=1;i<=n;i++) 
        change(root[i],root[i-1],0,mx,a[i]);
      while(m--){
        int b,x,l,r,s=0;
        read(b);read(x);read(l);read(r);
        for(int i=18;i>=0;i--){
          int t=1<<i;
          if((b&t)&&!query(root[r],root[l-1],
                      0,mx,s-x,s-x+t-1)) s+=t;
          if(!(b&t)&&query(root[r],root[l-1],
                      0,mx,s-x+t,s-x+2*t-1)) s+=t;
        }      
        printf("%d\n",b^s);
      }
    }
    
    • 1

    C59 可持久化线段树+异或+贪心 [SCOI2016] 美味

    信息

    ID
    6236
    时间
    3000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    4
    已通过
    3
    上传者