zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    深入理解java虚拟机笔记Chapter12
    深入理解java虚拟机笔记Chapter11
    深入理解java虚拟机笔记Chapter8
    深入理解java虚拟机笔记Chapter7
    深入理解java虚拟机笔记补充-JVM常见参数设置
    深入理解java虚拟机笔记Chapter4
    深入理解java虚拟机笔记Chapter3-内存分配策略
    Java从Txt文本进行数据提取
    C语言-格式输入输出中“%d,%o,%x,%e,%f,%s,%p”
    嵌入式学习书籍
  • 原文地址:https://www.cnblogs.com/20020723YJX/p/9384331.html
Copyright © 2011-2022 走看看