bzoj4571/luogu3293 美味 (主席树+贪心)

首先想到建出可持久化trie树然后在上面贪心,但是它加了一个数所以不能这么做

但依然可以贪心,仿照上面那个的过程,如果设y是在第i位上^b是1的数(前面的位数已经贪好了),我只要在[l,r]范围内能有[y-x,y+(1<<i)-x-1)]的数,那这位异或出来就是可以是1的

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=2e5+10,maxp=maxn*20;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 int root[maxn],N,M,L=100000;
16 int ch[maxp][2],v[maxp],pct;
17 
18 void insert(int pre,int &p,int l,int r,int x){
19     p=++pct;
20     v[p]=v[pre]+1;
21     if(l<r){
22         int m=l+r>>1;
23         if(x<=m) ch[p][1]=ch[pre][1],insert(ch[pre][0],ch[p][0],l,m,x);
24         else ch[p][0]=ch[pre][0],insert(ch[pre][1],ch[p][1],m+1,r,x);
25     }
26 }
27 
28 int query(int pre,int p,int l,int r,int x,int y){
29     if(x<=l&&r<=y) return v[p]-v[pre];
30     int m=l+r>>1,re=0;
31     if(x<=m) re=query(ch[pre][0],ch[p][0],l,m,x,y);
32     if(y>=m+1) re+=query(ch[pre][1],ch[p][1],m+1,r,x,y);
33     return re;
34 }
35 
36 inline int solve(int b,int x,int pre,int p){
37     int n=0;
38     for(int i=17;i>=0;i--){
39         int y=n|((((b>>i)&1)^1)<<i);
40         // printf("%d %d\n",n,y);
41         if(query(pre,p,0,L,max(0,y-x),min(L,y+(1<<i)-x-1))) n=y;
42         else if((b>>i)&1) n|=(1<<i);
43     }
44     return n^b;
45 }
46 
47 int main(){
48     //freopen("","r",stdin);
49     int i,j,k;
50     N=rd();M=rd();
51     for(i=1;i<=N;i++){
52         int a=rd();
53         insert(root[i-1],root[i],0,L,a);
54     }
55     for(i=1;i<=M;i++){
56         int b=rd(),x=rd(),l=rd(),r=rd();
57         printf("%d\n",solve(b,x,root[l-1],root[r]));
58     }
59     return 0;
60 }

 

转载于:https://www.cnblogs.com/Ressed/p/9782138.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值