[SCOI2016]美味 贪心+主席树

Posted 20020723yjx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SCOI2016]美味 贪心+主席树相关的知识,希望对你有一定的参考价值。

挺水的一道题。

题面传送门

题目大意:每个询问给出b,x,l,r,求[l~r]区间内b xor (x+a[i])    (l<=i<=r) 的最大值。

秒想到trie树上贪心?

好像还有加法啊,直接套可持久化trie树行不通,怎么玩呢。

假设目前处理到第j位,b转成二进制后第j位为1来考虑。设我们目前找到的数是ans,那么,如果有一个i在[l~r]内,且ans-x<=a[i]<=ans+(1<<j)-1-x,那么(a[i]+x)^b在第j位必定是1。如果第j位为0,同理,在下就不再赘述。

怎么处理某个区间内,在某个值域内的数是否存在?

于是就自然而然的想到了主席树。

咦,好像就可以A了诶。

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define ll long long
#define re register
#define inf 0x3f3f3f3f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug
");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
//const ll mod;
const ll MAXN=2e5+10;
inl ll read() {
    re ll x = 0; re int f = 1;
    char ch = getchar();
    while(ch<0||ch>9) { if(ch== - ) f = -1; ch = getchar(); }
    while(ch>=0&&ch<=9) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x * f;
}
inl char readc() {
    char ch=getchar();
    while((z<ch||ch<a)&&(Z<ch||ch<A)) ch=getchar();
    return ch;
}
inl void write(re ll x){
    if(x>=10)write(x/10);
    putchar(x%10+0);
}
inl void writeln(re ll x){
    if(x<0) {x=-x;putchar(-);}
    write(x); puts("");
}
inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
inl void FR() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
inl void FC() {
    fclose(stdin);
    fclose(stdout);
}
ll a[MAXN],tot,root[MAXN],ans,maxn;
struct Node {
    ll son[2],cnt;
}Tree[MAXN<<5];
ll insert(ll pre,ll x,ll l,ll r) {
    re ll t=++tot;Tree[t]=Tree[pre];Tree[t].cnt++;
    if(l==r) return t;
    re ll mid=(l+r)>>1;
    if(x<=mid) Tree[t].son[0]=insert(Tree[pre].son[0],x,l,mid);
    else Tree[t].son[1]=insert(Tree[pre].son[1],x,mid+1,r);
    return t;
}
ll query(ll x,ll y,ll L,ll R,ll l,ll r) {
    if(L<=l&&r<=R) return Tree[y].cnt-Tree[x].cnt;
    re ll mid=(l+r)>>1,sum=0;
    if(L<=mid) sum+=query(Tree[x].son[0],Tree[y].son[0],L,R,l,mid);
    if(R>mid) sum+=query(Tree[x].son[1],Tree[y].son[1],L,R,mid+1,r);
    return sum;
}
bool Query(ll l,ll r,ll L,ll R) {
    L=max(0ll,L);R=min(R,maxn);
    if(L>R) return false;
    return query(root[l],root[r],L,R,0,maxn);
}
int main() {
//  FR(); 
    re ll n=read(),m=read();
    for(re ll i=1;i<=n;i++) {a[i]=read();maxn=max(maxn,a[i]);}
    for(re ll i=1;i<=n;i++) {root[i]=insert(root[i-1],a[i],0,maxn);}
    for(re ll i=1;i<=m;i++) {
        re ll b=read(),x=read(),l=read(),r=read();ans=0;
        for(re ll j=20;~j;j--) {
            re ll t=ans+((1^((b>>j)&1))<<j);
            if(Query(l-1,r,t-x,t+(1<<j)-x-1)) ans=t;
            else ans+=((b>>j)&1)<<j;
        }
        writeln(ans^b);
    }
//  FC();
    return 0;
}

 

以上是关于[SCOI2016]美味 贪心+主席树的主要内容,如果未能解决你的问题,请参考以下文章

LibreOJ #2016. 「SCOI2016」美味

BZOJ4571[Scoi2016]美味 主席树

[BZOJ 4571][Scoi2016]美味(主席树)

bzoj 4571 [Scoi2016]美味——主席树

P3293 [SCOI2016]美味 主席树+最大异或路径

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