1. 程式人生 > 其它 >7.21考試總結(NOIP模擬22)[d·e·f]

7.21考試總結(NOIP模擬22)[d·e·f]

你駐足於春色中,於那獨一無二的春色之中。

前言

首先,這套題的暴力分數十分豐厚,大概是 81+89+30=200 。

T1 的特殊性質比較多,也都很好想,於是考場 81pts 是沒有問題的。

T2 暴力求出所有點的公共的 LCA 然後,暴力上跳然後標記一下就好了。

但是,但是,我高階資料結構學傻了,先是建了一棵虛樹,然後發現有些節點是不可以被刪去的。。

然後我就開始把虛樹上壓縮了的路徑在解壓回來,暴力高(莫名多了一個建虛樹的時間),喜掛 53pts

T3 樹狀陣列求逆序對可以把暴力複雜度中的一個 n 降低為 logn 然後就有了 30pts。

但是,我竟然成了 CE 選手。。(第一次發現C++11不讓用 rank 作為變數名)

T1 d

解題思路

對於所有的矩形,我們發現只有去掉當前長或者寬最小的才可以對答案有貢獻。

因此可以列舉對於長或者寬最小的矩形去掉的數量,然後取出最優解。

但是這樣的複雜度比正解多了一個 n 。

我們發現可以先把前 m 個寬最小的矩形先去掉,然後再一個一個恢復回來。

每恢復一個,就要再刪除一個長最小矩形,用優先佇列維護。

  • 注意:之前刪除過的矩形不可以再刪除一邊,記錄一下。。

code

暴力+特殊性質81pts

#include<bits/stdc++.h>
#define int long long
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=1e5+10,INF=1e9;
int T,n,m,ans;
bool flag,vis[N];
struct Node
{
	int x,y;
}s[N];
struct Node2
{
	int num,id;
}a[N],b[N];
bool comp1(Node x,Node y)
{
	return x.y<y.y;
}
void Sepcial_Judge1()
{
	sort(s+1,s+n+1,comp1);
	ans=s[m+1].x*s[m+1].y;
}
void Sepcial_Judge2()
{
	int minx=INF,miny=INF;
	for(int i=1;i<=n;i++)
	{
		minx=min(minx,s[i].x);
		miny=min(miny,s[i].y);
	}
	ans=minx*miny;
}
void Sepcial_Judge3()
{
	int maxn=0;
	for(int i=1;i<=n;i++)
		maxn=max(maxn,s[i].x*s[i].y);
	ans=maxn;
}
bool comp2(Node2 x,Node2 y)
{
	return x.num<y.num;
}
void solve()
{
	ans=0;
	for(int i=1;i<=n;i++)
	{
		a[i].num=s[i].x;
		b[i].num=s[i].y;
		a[i].id=b[i].id=i;
	}
	sort(a+1,a+n+1,comp2);
	sort(b+1,b+n+1,comp2);
	for(int res=0,pos,pos2;res<=m;res++)
	{
		pos=1;
		for(int i=1;i<=res;i++)
			vis[a[i].id]=true;
		pos2=res+1;
		for(int j=1;j<=m-res;j++)
		{
			while(vis[b[pos].id])
				pos++;
			vis[b[pos].id]=true;
		}
		while(vis[a[pos2].id])	pos2++;
		while(vis[b[pos].id])	pos++;
		ans=max(ans,a[pos2].num*b[pos].num);
		for(int i=1;i<=pos2;i++)
			vis[a[i].id]=false;
		for(int i=1;i<=pos;i++)
			vis[b[i].id]=false;
	}
}
signed main()
{
	T=read();
	while(T--)
	{
		n=read();
		m=read();
		flag=false;
		for(int i=1;i<=n;i++)
		{
			s[i].x=read();
			s[i].y=read();
			if(i!=1&&s[i-1].x!=s[i].x)
				flag=true;
		}
		if(!flag)	Sepcial_Judge1();
		else	if(!m)	Sepcial_Judge2();
		else	if(m==n-1)	Sepcial_Judge3();
		else	solve();
		printf("%lld\n",ans);
	}
	return 0;
}

正解

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Pass"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=1e5+10,INF=1e9;
int T,n,m,ans;
bool flag,vis[N],v2[N];
struct Node
{
	int x,y;
}s[N];
struct Node2
{
	int num,id;
	bool friend	operator <(Node2 x,Node2 y)
	{
		return x.num>y.num;
	}
}a[N],b[N];
priority_queue<Node2> q;
bool comp2(Node2 x,Node2 y)
{
	return x.num<y.num;
}
void solve()
{
	while(!q.empty())	q.pop();
	memset(vis,false,sizeof(vis));
	memset(v2,false,sizeof(v2));
	for(int i=1;i<=n;i++)
	{
		a[i].num=s[i].x;
		b[i].num=s[i].y;
		a[i].id=b[i].id=i;
	}
	sort(a+1,a+n+1,comp2);
	for(int i=1;i<=m;i++)
		vis[a[i].id]=true;
	for(int i=1;i<=n;i++)
		if(!vis[b[i].id])
			q.push(b[i]);
	ans=a[m+1].num*q.top().num;
	for(int res=m;res;res--)
	{
		vis[a[res].id]=false;
		q.push(b[a[res].id]);
		v2[q.top().id]=true;
		q.pop();
		if(v2[a[res].id])
			continue;
		ans=max(ans,q.top().num*a[res].num);
	}
}
signed main()
{
	T=read();
	while(T--)
	{
		n=read();
		m=read();
		for(int i=1;i<=n;i++)
		{
			s[i].x=read();
			s[i].y=read();
		}
		solve();
		printf("%lld\n",ans);
	}
	return 0;
}

T2 e

解題思路

直接在樹上的節點上建主席樹,歷史版本為每個節點的父親。

不難發現,\(|a_i-r|\) 最小的一定是 r 或者 r的前驅和後繼。

於是我們只需要查詢前驅後繼就好了,無非就是在大於 r 的區間中找最小值,在小於 r 的區間中找最大值。

這是第一種打法,給出 pyt 的 \(code\)

我的打法當然不同於別人了。只要可以找到比 r 小的數的個數也就是 r 的排名不久好了??

接下來就是查詢區間內排名第 k 大的數就好了(這不是板子??)。

查詢的時候注意一下邊界問題就好了。

當然這個題不用主席樹其實也可以:

發現暴力跳LCA是被第 8 個點卡住,但是線段樹套平衡樹套線段樹是卡在了第 7 個點。

因此 暴力加樹套樹可做!!!(JYFHYX的 \(code\)

code

暴力跳 LCA

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Pass"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=1e5+10,INF=1e9;
int n,m,lca,T,typ,opt,ans,las,s[N],q[N];
int tim,dfn[N],topp[N],siz[N],fa[N],son[N],dep[N];
bool vis[N];
struct Edge
{
	int tot,head[N],ver[N<<1],nxt[N<<1];
	void add(int x,int y)
	{
		ver[++tot]=y;
		nxt[tot]=head[x];
		head[x]=tot;
		ver[++tot]=x;
		nxt[tot]=head[y];
		head[y]=tot;
	}
}e1,e2;
inline void dfs1(int x)
{
	siz[x]=1;
	for(int i=e1.head[x];i;i=e1.nxt[i])
	{
		int to=e1.ver[i];
		if(siz[to])	continue;
		dep[to]=dep[x]+1;
		fa[to]=x;
		dfs1(to);
		siz[x]+=siz[to];
		if(siz[to]>siz[son[x]])
			son[x]=to;
	}
}
inline void dfs2(int x,int tp)
{
	dfn[x]=++tim;
	topp[x]=tp;
	if(son[x])
		dfs2(son[x],tp);
	for(int i=e1.head[x];i;i=e1.nxt[i])
	{
		int to=e1.ver[i];
		if(dfn[to])	continue;
		dfs2(to,to);
	}
}
inline int LCA(int x,int y)
{
	if(!x||!y)	return 0;
	while(topp[x]^topp[y])
	{
		if(dep[topp[x]]<dep[topp[y]])
			swap(x,y);
		x=fa[topp[x]];
	}
	if(dep[x]>dep[y])
		swap(x,y);
	return x;
}
inline void solve(int fro,int to)
{
	while(fro!=to)
	{
		if(vis[fro])	break;
		vis[fro]=true;
		ans=min(ans,abs(s[fro]-opt));
		fro=fa[fro];
	}
	vis[to]=true;
	ans=min(ans,abs(s[to]-opt));
}
signed main()
{
	n=read();
	T=read();
	typ=read();
	for(int i=1;i<=n;i++)
		s[i]=read();
	for(int i=1,x,y;i<n;i++)
	{
		x=read();
		y=read();
		e1.add(x,y);
	}
	dfs1(1);
	dfs2(1,1);
	while(T--)
	{
		memset(vis,false,sizeof(vis));
		vis[0]=true;
		ans=INF;
		opt=read();
		m=read();
		for(int i=1,x;i<=m;i++)
		{
			x=read();
			q[i]=(x-1+las*typ)%n+1;
		}
		if(m==1)
		{
			las=ans=abs(opt-s[q[1]]);
			printf("%lld\n",ans);
			continue;
		}
		lca=q[1];
		for(int i=2;i<=m;i++)
			lca=LCA(lca,q[i]);
		for(int i=1;i<=m;i++)
			solve(q[i],lca);
		las=ans;
		printf("%lld\n",ans);
	}
	return 0;
}

虛樹 36pts

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Pass"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=1e5+10,INF=1e9;
int n,m,root,rtdep,T,typ,opt,ans,las,s[N],q[N];
int top,sta[N];
int tim,dfn[N],topp[N],siz[N],fa[N],son[N],dep[N];
struct Edge
{
	int tot,head[N],ver[N<<1],nxt[N<<1];
	void add(int x,int y)
	{
		ver[++tot]=y;
		nxt[tot]=head[x];
		head[x]=tot;
//		/*
		ver[++tot]=x;
		nxt[tot]=head[y];
		head[y]=tot;
//		*/
	}
}e1,e2;
void dfs1(int x)
{
	siz[x]=1;
	for(int i=e1.head[x];i;i=e1.nxt[i])
	{
		int to=e1.ver[i];
		if(siz[to])	continue;
		dep[to]=dep[x]+1;
		fa[to]=x;
		dfs1(to);
		siz[x]+=siz[to];
		if(siz[to]>siz[son[x]])
			son[x]=to;
	}
}
void dfs2(int x,int tp)
{
	dfn[x]=++tim;
	topp[x]=tp;
	if(son[x])
		dfs2(son[x],tp);
	for(int i=e1.head[x];i;i=e1.nxt[i])
	{
		int to=e1.ver[i];
		if(dfn[to])	continue;
		dfs2(to,to);
	}
}
int LCA(int x,int y)
{
	if(!x||!y)	return 0;
	while(topp[x]^topp[y])
	{
		if(dep[topp[x]]<dep[topp[y]])
			swap(x,y);
		x=fa[topp[x]];
	}
	if(dep[x]>dep[y])
		swap(x,y);
	return x;
}
bool comp(int x,int y)
{
	return dfn[x]<dfn[y];
}
void build(int x)
{
	if(!top)
	{
		if(rtdep>dep[x])	root=x,rtdep=dep[x];
		sta[++top]=x;
		return ;
	}
	int lca=LCA(x,sta[top]);
	while(top>1&&dep[sta[top-1]]>dep[lca])
	{
//		cout<<sta[top-1]<<' '<<lca<<endl;
		e2.add(sta[top-1],sta[top]);
		top--;
	}
	if(dep[lca]<dep[sta[top]])
		e2.add(lca,sta[top--]);
	if(!top||sta[top]!=lca)
	{
		sta[++top]=lca;
		if(rtdep>dep[lca])	root=lca,rtdep=dep[lca];
	}
	sta[++top]=x;
	if(rtdep>dep[x])	root=x,rtdep=dep[x];
}
void solve(int fro,int to)
{
	while(fro!=to)
	{
//		f();
//		cout<<fro<<' '<<to<<endl;
//		cout<<fro<<endl;
		if(!fro)	break;
		ans=min(ans,abs(s[fro]-opt));
		fro=fa[fro];
	}
	ans=min(ans,abs(s[to]-opt));
}
void dfs3(int x,int fat)
{
//	cout<<x<<' '<<fat<<endl;
	if(!ans)	return ;
	for(int i=e2.head[x];i;i=e2.nxt[i])
	{
		int to=e2.ver[i];
		if(to==fat)	continue;
		solve(to,x);
		dfs3(to,x);
	}
}
signed main()
{
//	freopen("date.in","r",stdin);
	n=read();
	T=read();
	typ=read();
	for(int i=1;i<=n;i++)
		s[i]=read();
	for(int i=1,x,y;i<n;i++)
	{
		x=read();
		y=read();
		e1.add(x,y);
//		e1.add(y,x);
	}
	dfs1(1);
	dfs2(1,1);
//	f();
/*
	for(int i=1;i<=n;i++)
		cout<<dfn[i]<<' ';
*/
	while(T--)
	{
		e2.tot=top=0;
		ans=rtdep=INF;
		opt=read();
		m=read();
		memset(e2.head,0,sizeof(e2.head));
		for(int i=1,x;i<=m;i++)
		{
			x=read();
			q[i]=(x-1+las*typ)%n+1;
		}
		if(m==1)
		{
			las=ans=abs(opt-s[q[1]]);
			printf("%lld\n",ans);
			continue;
		}
		sort(q+1,q+m+1,comp);
	//	f();
	//	cout<<root<<endl;
		for(int i=1;i<=m;i++)
			build(q[i]);
	//	f();
		while(--top)
		{
		//	cout<<sta[top]<<' '<<sta[top+1]<<endl;
			e2.add(sta[top],sta[top+1]);
		}
//		f();
//		cout<<root<<endl;
		dfs3(root,0);
//		f();
		las=ans;
		printf("%lld\n",ans);
//		cout<<T<<endl;
	}
//	f();
	return 0;
}

正解

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Pass"<<endl;
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=5e5+10,INF=1e18;
int n,m,lca,T,typ,opt,ans,las,s[N];
int tim,dfn[N],topp[N],siz[N],fa[N],son[N],dep[N];
int all,root[N];
int cnt,lsh[N];
vector<int> v[N];
struct Edge
{
	int tot,head[N],ver[N<<1],nxt[N<<1];
	void add(int x,int y)
	{
		ver[++tot]=y;
		nxt[tot]=head[x];
		head[x]=tot;
		ver[++tot]=x;
		nxt[tot]=head[y];
		head[y]=tot;
	}
}e;
struct Segment_Tree
{
	int l,r,dat;
}tre[N*80];
struct Ques
{
	int dat,cnt;
}q[N];
inline void dfs1(int x)
{
	siz[x]=1;
	for(int i=e.head[x];i;i=e.nxt[i])
	{
		int to=e.ver[i];
		if(siz[to])	continue;
		dep[to]=dep[x]+1;
		fa[to]=x;
		dfs1(to);
		siz[x]+=siz[to];
		if(siz[to]>siz[son[x]])
			son[x]=to;
	}
}
inline void dfs2(int x,int tp)
{
	dfn[x]=++tim;
	topp[x]=tp;
	if(son[x])
		dfs2(son[x],tp);
	for(int i=e.head[x];i;i=e.nxt[i])
	{
		int to=e.ver[i];
		if(dfn[to])	continue;
		dfs2(to,to);
	}
}
inline int LCA(int x,int y)
{
	if(!x||!y)	return 0;
	while(topp[x]^topp[y])
	{
		if(dep[topp[x]]<dep[topp[y]])
			swap(x,y);
		x=fa[topp[x]];
	}
	if(dep[x]>dep[y])
		swap(x,y);
	return x;
}
int insert(int pre,int l,int r,int val)
{
	int x=++all,mid=(l+r)>>1;
	tre[x].dat=tre[pre].dat+1;
	if(l>=r)	return x;
	ls=tre[pre].l;
	rs=tre[pre].r;
	if(val<=mid)	ls=insert(tre[pre].l,l,mid,val);
	else	rs=insert(tre[pre].r,mid+1,r,val);
	return x;
}
int query_rank(int pre,int x,int l,int r,int val)
{
	if(l==r)	return tre[x].dat-tre[pre].dat;
	int mid=(l+r)>>1;
	int sum=tre[tre[x].l].dat-tre[tre[pre].l].dat;
	if(val<=mid)	return query_rank(tre[pre].l,tre[x].l,l,mid,val);
	return sum+query_rank(tre[pre].r,tre[x].r,mid+1,r,val);
}
int query(int pre,int x,int l,int r,int rk)
{
	if(l>=r)	return l;
	int mid=(l+r)>>1;
	int sum=tre[tre[x].l].dat-tre[tre[pre].l].dat;
	if(rk<=sum)	return query(tre[pre].l,tre[x].l,l,mid,rk);
	return query(tre[pre].r,tre[x].r,mid+1,r,rk-sum);
}
void dfs3(int x)
{
	root[x]=insert(root[fa[x]],1,cnt,s[x]);
	for(int i=e.head[x];i;i=e.nxt[i])
	{
		int to=e.ver[i];
		if(to==fa[x])	continue;
		dfs3(to);
	}
}
signed main()
{
	n=read();
	T=read();
	typ=read();
	for(int i=1;i<=n;i++)
		lsh[i]=s[i]=read();
	for(int i=1,x,y;i<n;i++)
	{
		x=read();
		y=read();
		e.add(x,y);
	}
	dfs1(1);
	dfs2(1,1);
	for(int i=1,m;i<=T;i++)
	{
		lsh[i+n]=q[i].dat=read();
		m=read();
		for(int j=1,x;j<=m;j++)
		{
			x=read();
			v[i].push_back(x);
		}
	}
	sort(lsh+1,lsh+n+T+1);
	cnt=unique(lsh+1,lsh+n+T+1)-lsh-1;
	for(int i=1;i<=n;i++)
		s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh;
	for(int i=1;i<=T;i++)
		q[i].dat=lower_bound(lsh+1,lsh+cnt+1,q[i].dat)-lsh;
	dfs3(1);
	for(int i=1;i<=T;i++)
	{
		for(int j=0;j<v[i].size();j++)
			v[i][j]=(v[i][j]-1+ans*typ)%n+1;
		ans=INF;
		int lca=v[i][0];
		for(int j=1;j<v[i].size();j++)
			lca=LCA(lca,v[i][j]);
		lca=fa[lca];
		for(int j=0;j<v[i].size();j++)
		{
			int num=v[i][j],minn,maxn,temp=INF;
			int rk=query_rank(root[lca],root[num],1,cnt,q[i].dat);
			if(rk<=1)	minn=query(root[lca],root[num],1,cnt,1);
			else	minn=query(root[lca],root[num],1,cnt,rk-1);
			if(rk>=tre[root[num]].dat-tre[root[lca]].dat)	maxn=query(root[lca],root[num],1,cnt,rk);
			else	maxn=query(root[lca],root[num],1,cnt,rk+1);
			if(rk>=1&&rk<=tre[root[num]].dat-tre[root[lca]].dat)
				temp=query(root[lca],root[num],1,cnt,rk);
			ans=min(ans,min(abs(lsh[q[i].dat]-lsh[minn]),abs(lsh[maxn]-lsh[q[i].dat])));
			if(temp!=INF)	ans=min(ans,abs(lsh[q[i].dat]-lsh[temp]));
		}
		printf("%lld\n",ans);
	}
	return 0;
}

T3 f

解題思路

非常妙的一個題,有一個取一半的思想非常的重要。

對於 \(xor\) 的操作顯然是應該拆位的,於是每一個數就會變成一個 01 串。

因此可以用 Tire 樹進行維護,從而求出序列中每一位的逆序對的個數(描述的不太好,意會一下)

然後 \(xor\) 操作,直接是 0 就直接計算,是 1 的話就需要算入另一種情況的逆序對的個數。

但是,發現對於 \(2^{30}\) 的資料哪怕是 n 的複雜度也是搞不掉的,考慮把一個數"掰開"

於是我們可以發現對於大於 \(2^{\frac{k}{2}}\) 的數,其實他的前 \(\dfrac{k}{2}\) 位是在 \(2^{\frac{k}{2}}\) 已經計算過了的,因此只需要再開一個數組記錄後面幾位的就好了。

然後我們發現時間複雜度還滿足一個 log 的空餘,誒,二分答案。。

逆序對的個數上的 f 陣列是滿足單調性的,因此對於逆序對個數進行二分。

如果小於當前掃描值的個數的數小於 p 那麼就記錄答案並查詢右區間。

對於二分答案函式的處理就簡單許多了,首先對於之前搞得兩半的 f 陣列分別排一下序。

然後這樣就滿足單調性了,接下來雙指標(此雙指標非彼雙指標)分別掃兩個陣列。

這樣就可以得到符合答案的值了,對於符合的值的下標的查詢也是類似。

更改一下條件就可以了,對於等於 \(f(ans)\) 的都給記錄下來,然後給下標排個序就好了。

code

30pts 樹狀陣列

#include<bits/stdc++.h>
#define int long long
#define ls x<<1
#define rs x<<1|1
#define f() cout<<"Pass"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=5e5+10;
int n,k,rank,s[N],q[N],a[N],f[N],id[N];
int tre[N],lsh[N],cnt;
int lowbit(int x)
{
	return x&(-x);
}
void Special_Judge1()
{
	printf("%lld %lld",rank-1,rank-1);
	exit(0);
}
bool comp(int x,int y)
{
	if(f[x]==f[y])	return x<y;
	return f[x]<f[y];
}
void add(int x,int num)
{
	for(int i=x;i<=n;i+=lowbit(i))
		tre[i]+=num;
}
int ask(int x)
{
	int sum=0;
	for(int i=x;i;i-=lowbit(i))
		sum+=tre[i];
	return sum;
}
void Special_Judge2()
{
	for(int x=0;x<(1<<k);x++)
	{
		memset(tre,0,sizeof(tre));
		id[x]=x;
		for(int i=1;i<=n;i++)
			lsh[i]=q[i]=(s[i]^x)+2;
		sort(lsh+1,lsh+n+1);
		cnt=unique(lsh+1,lsh+n+1)-lsh-1;
		for(int i=n;i>=1;i--)
		{
			q[i]=lower_bound(lsh+1,lsh+cnt+1,q[i])-lsh+1;
			f[x]+=ask(q[i]-1);
			add(q[i],1);
		}
	}
	sort(id+0,id+(1<<k),comp);
	printf("%lld %lld",f[id[rank-1]],id[rank-1]);
	exit(0);
}
void solve()
{
	int x=rank-1;
	for(int i=1;i<=n;i++)
		q[i]=s[i]^x;
	for(int i=2;i<=n;i++)
		for(int j=i-1;j>=1;j--)
			if(q[i]<q[j])
				a[i]++;
	for(int i=1;i<=n;i++)
		f[x]+=a[i];
	printf("%lld %lld",f[x],x);
}
signed main()
{
	n=read();
	k=read();
	rank=read();
	for(int i=1;i<=n;i++)
		s[i]=read();
	if(k==0)	Special_Judge1();
	if(k<=10)	Special_Judge2();
	solve();
	return 0;
}

正解

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Pass"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
const int N=5e5+10;
int n,rk,k,num,ans,s[N];
int all=1,cnt[N*40][2];
int top,sta[N*40];
struct Tire
{
	int dat,ch[2];
}tre[N*40];
struct Storage
{
	int dat,id;
}f1[N],f2[N];
void insert(int val)
{
	int rt=1;
	for(int i=k-1;i>=0;i--)
	{
		if(!tre[rt].ch[(val>>i)&1])	tre[rt].ch[(val>>i)&1]=++all;
		cnt[i][(val>>i)&1]+=tre[tre[rt].ch[((val>>i)&1)^1]].dat;
		tre[tre[rt].ch[(val>>i)&1]].dat++;
		rt=tre[rt].ch[(val>>i)&1];
	}
}
bool comp(Storage x,Storage y)
{
	if(x.dat!=y.dat)	return x.dat<y.dat;
	return x.id<y.id;
}
bool judge(int val)
{
	int total=0,sum=(1<<(k-k/2))-1;
	for(int i=0;i<(1<<(k/2));i++)
	{
		if(f1[i].dat>val)	break;
		while(sum>=0&&f1[i].dat+f2[sum].dat>=val)	sum--;
		total+=sum+1;
	}
	if(total<rk)	num=total;
	return total<rk;
}
int solve()
{
	int sum=(1<<(k-k/2))-1;
	for(int i=0;i<(1<<(k/2));i++)
	{
		if(f1[i].dat>ans)	break;
		while(sum>=0&&f1[i].dat+f2[sum].dat>ans)
			sum--;
		if(f2[sum].dat+f1[i].dat==ans)	sta[++top]=f2[sum].id*(1<<k/2)+f1[i].id;
	}
	sort(sta+1,sta+top+1);
	return sta[rk-num];
}
signed main()
{
	n=read();
	k=read();
	rk=read();
	for(int i=1;i<=n;i++)
	{
		s[i]=read();
		insert(s[i]);
	}
	for(int i=0;i<(1<<(k/2));i++)
	{
		for(int j=0;j<k/2;j++)
			f1[i].dat+=cnt[j][(i>>j)&1];
		f1[i].id=i;
	}
	for(int i=0;i<(1<<(k-k/2));i++)
	{
		for(int j=k/2;j<k;j++)
			f2[i].dat+=cnt[j][((i>>(j-k/2))&1)];
		f2[i].id=i;
	}
	sort(f1+0,f1+(1<<(k/2)),comp);
	sort(f2+0,f2+(1<<(k-k/2)),comp);
	int l=0,r=n*(n-1)/2;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(judge(mid))
		{
			l=mid+1;
			ans=mid;
		}
		else	r=mid-1;
	}
	printf("%lld %lld",ans,solve());
	return 0;
}