[BZOJ4571][SCOI2016]美味(贪心+主席树)

经典问题,按位贪心,每次需要知道的是”在这一位之前的位都以确定的情况下,能否找到这一位是0/1的数”,这就是在询问[L,R]内某个值域区间是否有数,主席树即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 const int N=200010,M=300000;
 7 int n,m,b,x,l,r,nd,rt[N],a[N],ls[N*20],rs[N*20],v[N*20];
 8 
 9 void ins(int &x,int y,int L,int R,int pos){
10     x=++nd; v[x]=v[y]+1; ls[x]=ls[y]; rs[x]=rs[y];
11     if (L==R) return;
12     int mid=(L+R)>>1;
13     if (pos<=mid) ins(ls[x],ls[y],L,mid,pos);
14         else ins(rs[x],rs[y],mid+1,R,pos);
15 }
16 
17 int que(int x,int y,int L,int R,int l,int r){
18     if (L==l && r==R) return v[y]-v[x];
19     int mid=(L+R)>>1;
20     if (r<=mid) return que(ls[x],ls[y],L,mid,l,r);
21     else if (l>mid) return que(rs[x],rs[y],mid+1,R,l,r);
22         else return que(ls[x],ls[y],L,mid,l,mid)+que(rs[x],rs[y],mid+1,R,mid+1,r);
23 }
24 
25 int main(){
26     freopen("bzoj4571.in","r",stdin);
27     freopen("bzoj4571.out","w",stdout);
28     scanf("%d%d",&n,&m);
29     rep(i,1,n) scanf("%d",&a[i]),ins(rt[i],rt[i-1],0,M,a[i]);
30     rep(i,1,m){
31         scanf("%d%d%d%d",&b,&x,&l,&r); int a=0;
32         for (int j=17; ~j; j--){
33             if (!(b&(1<<j))) a|=1<<j;
34             int L=max(a-x,0),R=(a|((1<<j)-1))-x;
35             if (R<0 || !que(rt[l-1],rt[r],0,M,L,R)) a^=1<<j;
36         }
37         printf("%d\n",a^b);
38     }
39     return 0;
40 }

 

转载于:https://www.cnblogs.com/HocRiser/p/10090374.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值