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
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>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<=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<

你可能感兴趣的:(CF-Technocup3 D Optimal Subsequences)