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 MBSubmit: 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
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