zoukankan      html  css  js  c++  java
  • luogu P3293 [SCOI2016]美味

    传送门

    异或最大值应该是要用(trie)树,从高位往低位贪心,虽然这里询问区间的数都要加上(x),但是仍然可以利用这个思想

    从高往低位考虑,我们要找一个加上(x)后当前二进制位(j)不等于(b)的当前位的数,假设(b)当前位为0,我们就要现在找个数加上(x)后当前位(j)为1,记之前选出的数为(ans),那么我们就要找一个在([ans+(1<<j)-x,ans+(1<<j)-(1<<j)-1-x])区间内的数;如果(b)当前位为1,那么取值范围为([ans-x,ans-(1<<j)-1-x]).如果有这个数,那么(ans)当前位(j)就可以等于(b)当前位(xor 1),否则就反过来

    这个操作可以用主席树查询某区间的数出现次数的操作实现

    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define eps (1e-7)
    
    using namespace std;
    const int N=500000+10;
    const LL inf=1ll<<45;
    il LL rd()
    {
      re LL x=0,w=1;re char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    
    #define mid ((l+r)>>1)
    
    int s[N*20],ch[N*20][2],rt[N],tt;
    int n,m,kk,L,R,a[N];
    il void inst(int p)
    {
      rt[p]=++tt;
      int o1=rt[p],o2=rt[p-1],l=0,r=n;
      s[o1]=s[o2]+1;
      do
        {
          if(a[p]<=mid)
        {
          ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
          o1=ch[o1][0],o2=ch[o2][0],r=mid;
        }
          else
        {
          ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
          o1=ch[o1][1],o2=ch[o2][1],l=mid+1;
        }
          s[o1]=s[o2]+1;
        }
      while(l<r);
    }
    int quer(int o1,int o2,int l,int r,int ll,int rr)
    {
      if(ll<=l&&r<=rr) return s[o1]-s[o2];
      int an=0;
      if(ll<=mid) an+=quer(ch[o1][0],ch[o2][0],l,mid,ll,rr);
      if(rr>mid) an+=quer(ch[o1][1],ch[o2][1],mid+1,r,ll,rr);
      return an;
    }
    bool ok(int l,int r,int ll,int rr)
    {
      ll=max(ll,0),rr=min(rr,n);
      return ll<=rr?quer(rt[r],rt[l-1],0,n,ll,rr):0;
    }
    int q;
    
    int main()
    {
      ///no O2
      m=rd(),q=rd();
      for(int i=1;i<=m;i++) n=max(n,a[i]=rd());
      for(int i=1;i<=m;i++) inst(i);
      while(q--)
        {
          int b=rd(),x=rd(),ll=rd(),rr=rd(),ans=0;
          for(int i=17;i>=0;i--)
            {
              int nw=ans|(((b>>i&1)^1)<<i);
              if(ok(ll,rr,nw-x,nw+(1<<i)-1-x)) ans=nw;
              else ans|=(b>>i&1)<<i;
            }
          printf("%d
    ",ans^b);
        }
      return 0;
    }
    
    
  • 相关阅读:
    dsu on tree题表
    [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)
    [BZOJ3757]苹果树(树上莫队)
    [BZOJ3585]mex(莫队+分块)
    Prufer codes与Generalized Cayley's Formula
    [luogu4459][BJOI2018]双人猜数游戏(DP)
    [BZOJ5292][BJOI2018]治疗之雨(概率DP+高斯消元)
    [BZOJ5291][BJOI2018]链上二次求和(线段树)
    [luogu4389]付公主的背包(多项式exp)
    [CF1086E]Beautiful Matrix(容斥+DP+树状数组)
  • 原文地址:https://www.cnblogs.com/smyjr/p/9739276.html
Copyright © 2011-2022 走看看