BZOJ3689: 异或之

题解:类似与超级钢琴的做法 直接用堆维护即可  (

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,k,cnt;
int a[MAXN],rt[MAXN],tag[MAXN*32];
typedef struct node{
    int l,r,sum;
}node;
node d[MAXN*32];
void insert(int x,int k,int id){
    for(int i=30;i>=0;i--){
        if(k&(1<<i)){
            int t=++cnt;d[t]=d[d[x].r];d[x].r=t;d[t].sum++;
            x=t;
        }
        else{
            int t=++cnt;d[t]=d[d[x].l];d[x].l=t;d[t].sum++;
            x=t;
        }
    }
    tag[x]=id;
}
pair<int,int> querty(int x,int y,int k){
    int res=0;
    for(int i=30;i>=0;i--){
        if(k&(1<<i)){
            if(d[d[y].r].sum-d[d[x].r].sum)res+=(1<<i),x=d[x].r,y=d[y].r;
            else x=d[x].l,y=d[y].l;
        }
        else{
            if(d[d[y].l].sum-d[d[x].l].sum)x=d[x].l,y=d[y].l;
            else res+=(1<<i),x=d[x].r,y=d[y].r;
        }
    }
    res^=k;
    return mp(tag[y],res);
}
typedef struct Tmp{
    int pos,l,r,key,aim;
    friend bool operator<(Tmp aa,Tmp bb){return aa.key>bb.key;}
}Tmp;
priority_queue<Tmp>que;
vector<int>vec;
int main(){
    n=read();k=read();cnt=0;
    rt[0]=++cnt;insert(rt[0],0,0);
    inc(i,1,n)a[i]=read(),rt[i]=++cnt,d[rt[i]]=d[rt[i-1]],insert(rt[i],a[i],i);
    inc(i,2,n){
        pair<int,int> t=querty(rt[0],rt[i-1],a[i]);
        que.push((Tmp){t.first,1,i-1,t.second,i});
    }
    pair<int,int> t1;
    for(int i=1;i<=k;i++){
        vec.pb((que.top()).key);
        Tmp t=que.top();que.pop();printf("%d ",t.key);
        if(t.pos>t.l)t1=querty(rt[t.l-1],rt[t.pos-1],a[t.aim]),que.push((Tmp){t1.first,t.l,t.pos-1,t1.second,t.aim});
        if(t.pos<t.r)t1=querty(rt[t.pos],rt[t.r],a[t.aim]),que.push((Tmp){t1.first,t.pos+1,t.r,t1.second,t.aim});
    }
}

  

3689: 异或之

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 550  Solved: 269
[Submit][Status][Discuss]

Description

给定n个非负整数A[1], A[2], ……, A[n]。
对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。
注:xor对应于pascal中的“xor”,C++中的“^”。

Input

第一行2个正整数 n,k,如题所述。
以下n行,每行一个非负整数表示A[i]。

Output

 共一行k个数,表示前k小的数。

Sample Input

4 5
1
1
3
4

Sample Output

0 2 2 5 5

HINT

 

【样例解释】

1 xor 1 = 0 (A[1] xor A[2])

1 xor 3 = 2 (A[1] xor A[3])

1 xor 4 = 5 (A[1] xor A[4])

1 xor 3 = 2 (A[2] xor A[3])

1 xor 4 = 5 (A[2] xor A[4])

3 xor 4 = 7 (A[3] xor A[4])

前5小的数:0 2 2 5 5

【数据范围】

 对于100%的数据,2 <= n <= 100000; 1 <= k <= min{250000, n*(n-1)/2};

        0 <= A[i] < 2^31

posted @ 2018-09-29 12:29  wang9897  阅读(151)  评论(0编辑  收藏  举报