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的關係就好。
其實離線搞更方便一些,也不用可持久化。。
上代碼c++

#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;
}
相關文章
相關標籤/搜索