NOIP 模擬 $22\; \rm f$
阿新 • • 發佈:2021-07-22
題解
題解 \(by\;zj\varphi\)
對於一個數,如果它二進位制下第 \(i\) 位為 \(1\),那麼 \(\rm x\) 在這一位選 \(1\) 的貢獻就是和它不同的最高為為 \(i\) 的數的個數
這個東西很好搞,整一個 \(\rm 01trie\) 就行,每會插入的時候直接統計即可
但是如何求第 \(p\) 位,二分,但每回二分時 \(2^k\) 搜尋一遍就超時了,\(\rm meet\;in\;the\;middle\)
發現每一位是相互獨立的,也就是說它們之間是不會互相影響的,所以將二進位制位割半,分別排個序,之後對於一個序列用指標從小往大搜,同時維護另一個指標,而這個指標一定是單調遞減的;
所以複雜度就是 \(2^\frac{k}{2}log\frac{n×(n-1)}{2}\)
對於第二問,對於大的那一半開個桶,維護它能在小的那一半匹配上的數,最後按大的排序,跳區間,每次判斷這個數匹配上的 \(siz\) 是否大於 \(p\),若大於就在區間內暴力,可以保證複雜度不會超過 \(2^\frac{k}{2}\)
所以總複雜度為 \(\mathcal O\rm (nk+2^\frac{k}{2}log\frac{n×(n-1)}{2}+2^\frac{k}{2})\)
Code
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i using namespace std; namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++ template<typename T>inline void read(T &x) { ri f=1;x=0;register char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();} x=f?x:-x; } } using IO::read; namespace nanfeng{ #define pb(x) push_back(x) #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} typedef long long ll; static const int N=5e5+7; int a[N],tmp[N],st[N],pg[1<<16],id[1<<16],cnt1,cnt2,cnt,n,k,p,mx,hk,kh,S1,S2,bs,num,ans; ll al,del[33]; vector<int> sg[1<<16]; struct slv{ll f;int id;}so1[1<<16],so2[1<<16]; inline int operator<(const slv &s1,const slv &s2) {return s1.f<s2.f;} struct BIT{ #define lowbit(x) ((x)&-(x)) int c[N]; inline void update(int x) {for (ri i(x);i<=mx;i+=lowbit(i)) p(c[i]);} inline int query(int x) { int res(0); for (ri i(x);i;i-=lowbit(i)) res+=c[i]; return res; } }B; struct Trie{ #define sn(x,u) T[x].ch[u] struct trie{int ch[2],sz;}T[N*30]; int tot; Trie(){tot=1;} inline void insert(int nw) { int p=1; for (ri i(29);~i;--i) { ri cur=(nw>>i)&1; if (!cur) del[i]-=T[sn(p,cur^1)].sz; else del[i]+=T[sn(p,cur^1)].sz; if (!sn(p,cur)) sn(p,cur)=p(tot); p=sn(p,cur); p(T[p].sz); } } }T; inline void init() { sort(tmp+1,tmp+n+1); int k=unique(tmp+1,tmp+n+1)-tmp; for (ri i(1);i<=n;p(i)) st[i]=lower_bound(tmp+1,tmp+k,st[i])-tmp; mx=k-1; for (ri i(n);i;--i) { al+=B.query(st[i]-1); B.update(st[i]); } } inline int check(ll f) { ri p2=1; num=0; for (ri p1(cnt1);p1;--p1) { while(p2<=cnt2&&so2[p2].f+so1[p1].f+al<=f) p(p2); num+=p2-1; } return num>=p; } inline void checka(ll f) { ri p1=1,tmp; num=0; for (ri p2(cnt2);p2;--p2) { p(cnt); id[pg[cnt]=cnt]=so2[p2].id; while(p1<=cnt1&&so2[p2].f+so1[p1].f+al<f) p(p1); tmp=0; while(p1<=cnt1&&so2[p2].f+so1[p1].f+al==f) { p(tmp); sg[cnt].pb(so1[p1].id); p(p1); } num+=p1-1-tmp; } } inline int cmp(int x,int y) {return id[x]<id[y];} inline int main() { // FI=freopen("nanfeng.in","r",stdin); // FO=freopen("nanfeng.out","w",stdout); read(n),read(k),read(p); for (ri i(1);i<=n;p(i)) read(a[i]),st[i]=tmp[i]=a[i]; init(); for (ri i(1);i<=n;p(i)) T.insert(a[i]); hk=k>>1,kh=k-hk; bs=(S1=(1<<hk)-1)+1; S2=((1<<kh)-1)<<hk; for (ri i(0);i<=S1;p(i)) { ll tmp=0; for (ri j(0);j<hk;p(j)) if ((i>>j)&1) tmp+=del[j]; so1[p(cnt1)].f=tmp; so1[cnt1].id=i; } for (ri i(0);i<=S2;i+=bs) { ll tmp=0; for (ri j(hk);j<k;p(j)) if ((i>>j)&1) tmp+=del[j]; so2[p(cnt2)].f=tmp; so2[cnt2].id=i; } sort(so1+1,so1+cnt1+1); sort(so2+1,so2+cnt2+1); ll l=0,r=(ll)n*(n-1)/2,res(0); while(l<=r) { ll mid=(l+r>>1ll); if (check(mid)) r=mid-1,res=mid; else l=mid+1; } checka(res); sort(pg+1,pg+cnt+1,cmp); p-=num; for (ri i(1);i<=cnt;p(i)) { int cur=pg[i],siz=sg[cur].size(); if (p>siz) p-=siz; else { sort(sg[cur].begin(),sg[cur].end()); ans=id[cur]|sg[cur][p-1]; break; } } printf("%lld %d\n",res,ans); return 0; } } int main() {return nanfeng::main();}