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;
    }
    
    
  • 相关阅读:
    获取系统环境变量
    改变系统提示信息
    获取任务栏大小
    获取系统启动后经过的时间
    获取系统版本号
    z-tree的使用
    vue学习-day05 -- 案例:名字合并(监听data数据的改变)
    vue学习-day04(路由)
    eclipse在线安装ermaster插件
    vue学习-day03(动画,组件)
  • 原文地址:https://www.cnblogs.com/smyjr/p/9739276.html
Copyright © 2011-2022 走看看