BZOJ3689 异或之

题目链接:戳我

十二省联考day1t1的近似原题啊!!!
就是维护一个可持久化01trie,(可持久化01trie当然可以维护区间第K大啦!)然后一个二元组,放到优先队列里面。
先放入以每一个点为右端点的异或最小值,取出之后放次小值,再取出之后放次次小值.......

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define MAXN 500010
using namespace std;
int n,tot=1,K;
int rt[MAXN],cnt[MAXN<<5],t[MAXN<<5][2];
long long a[MAXN];
struct Node
{
    int pos,maomao;
    long long sum;
    friend bool operator < (Node x,Node y)
        {return x.sum>y.sum;}
    Node(int x,int y,long long z):pos(x),maomao(y),sum(z){};
};
priority_queue<Node>q;
inline void insert(int &x,int f,long long sum,int k)
{
    x=++tot;
    cnt[x]=cnt[f]+1;
    t[x][0]=t[f][0],t[x][1]=t[f][1];
    if(k<0) return;
    int cur=((sum>>k)&1);
    if(!cur) 
        insert(t[x][0],t[f][0],sum,k-1);
    else 
        insert(t[x][1],t[f][1],sum,k-1);
}
inline long long query(int x,long long sum,int k)
{
    // printf("x=%d sum=%lld k=%d\n",x,sum,k);
    long long cur_ans=0;
    for(int i=31;i>=0;i--)
    {
        int cur=(sum>>i)&1;
        if(!cur)
        {
            if(k<=cnt[t[x][0]]) x=t[x][0],cur_ans=(cur_ans<<1);
            else k-=cnt[t[x][0]],x=t[x][1],cur_ans=(cur_ans<<1)|1;
        }
        else 
        {
            if(k<=cnt[t[x][1]]) x=t[x][1],cur_ans=(cur_ans<<1);
            else k-=cnt[t[x][1]],x=t[x][0],cur_ans=(cur_ans<<1)|1;
        }
    }
    return cur_ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    freopen("ce.out","w",stdout);
    #endif
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    rt[0]=1;
    for(int i=1;i<=n;i++) insert(rt[i],rt[i-1],a[i],31);
    // for(int i=1;i<=n;i++) printf("rt[%d]=%d\n",i,rt[i]);
    for(int i=2;i<=n;i++)
    {
        long long cur_ans=query(rt[i-1],a[i],1);
        // printf("i=%d sum=%lld cur_ans=%lld\n",i,a[i],cur_ans);
        q.push((Node){i,1,cur_ans});
    }
    for(int primy=1;primy<=K;primy++)
    {
        Node u=q.top();q.pop();
        printf("%lld ",u.sum);
        u.maomao++;
        if(u.maomao>u.pos-1) continue;
        long long cur_ans=query(rt[u.pos-1],a[u.pos],u.maomao);
        // printf("pos=%d sum=%lld cur_ans=%lld\n",u.pos,a[u.pos],cur_ans);
        u.sum=cur_ans;
        q.push(u);
        // cout<<endl;
    }
    return 0;
}
posted @ 2019-04-25 16:41  风浔凌  阅读(182)  评论(0编辑  收藏  举报