CF-Technocup3 D Optimal Subsequences

D Optimal Subsequences

http://codeforces.com/contest/1227/problem/D2
显然,每次求的k一定是这个序列从大到小排序后前k大的元素。
考虑如何做才能使其字典序最小。我们设p为第k大的元素。
首先,这k个数是确定的。
其次,对于比p大的所有元素,他们是必须选的。
所以,欲使这个序列字典序最小,其实就是让所有p出现的位置
尽量靠前。
那做法就很显然了:先离散化,搞出来一个相对排名,用主席树
维护相对排名。每次查询,二分答案,check就查一下root[1]到
root[mid]中权值排名大于p的排名+min(p的上限个数,root[1]
到root[mid]中p的出现次数)和pos的关系就好。
其实离线搞更方便一些,也不用可持久化。。
上代码

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
I read(int &res){
	res=0;re g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
struct P{
	int w,id,v;
	friend bool operator < (P x,P y){
		return x.w>y.w;
	}
}p[202000];
struct Tree{
	int lc,rc,w;
}t[6060000];
#define L t[k].lc
#define R t[k].rc
int n,m,tot,X,Y,sum,pos,lim,a[202000],b[202000],f[202000],len[202000],root[202000];
I modi(int &k,int k1,int l,int r,int x){
	k=++tot;
	L=t[k1].lc;R=t[k1].rc;t[k].w=t[k1].w;
	if(l==r){
		t[k].w++;
		return;
	}
	re mid=(l+r)>>1;
	if(x<=mid)modi(L,t[k1].lc,l,mid,x);
	else modi(R,t[k1].rc,mid+1,r,x);
	t[k].w=t[L].w+t[R].w;
}
IN ques(int k,int l,int r,int x,int y){
	if(x>r||y<l)return 0;
	if(x<=l&&r<=y)return t[k].w;
	re mid=(l+r)>>1;
	return ques(L,l,mid,x,y)+ques(R,mid+1,r,x,y);
}
IN divided(int x,int y){
	if(x==y)return x;
	re mid=(x+y)>>1;
	//cout<<ques(root[mid],1,sum,1,pos)<<"!"<<endl;
	if(ques(root[mid],1,sum,1,pos-1)+min(ques(root[mid],1,sum,pos,pos),lim)>=Y)y=mid;
	else x=mid+1;
	return divided(x,y);
}
int main(){
	read(n);
	F(i,1,n){
		read(a[i]);
		p[i].w=a[i];
		p[i].id=i;
	}
	sort(p+1,p+1+n);
	m=0;
	p[0].w=p[1].w+1;
	f[0]=0;
	F(i,1,n){
		if(p[i].w!=p[i-1].w)m++,f[m]=i;
		b[p[i].id]=m;
		p[i].v=m;
	}
	tot=0;
	sum=m;
	//cout<<sum<<endl;
	F(i,1,n){
		modi(root[i],root[i-1],1,sum,b[i]);
	}
	read(m);
	while(m--){
		read(X);read(Y);
		pos=p[X].v;lim=X-f[pos]+1;
		//cout<<pos<<" ";
		int P=divided(1,n);
		//cout<<P<<" ";
		cout<<a[P]<<endl;
	}
	return 0;
}
posted @ 2019-11-26 20:24  Purple_wzy  阅读(111)  评论(0编辑  收藏  举报