Sequence

来源:互联网 发布:美国经济数据日历 编辑:程序博客网 时间:2024/06/08 18:34

题目大意

有两个序列a和b。
每次询问将一个区间a值排名在[x,y]的中找一个b值第k小。

做法

用主席树将排名的x和y变成具体的值。
接下来可以根据b整体二分,其余部分可以拆区间+扫描线+数据结构完成。

#pragma GCC optimize(2)#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=30000+10,maxm=100000+10,maxtot=1000000+10;struct dong{    int x,ca,wz;} c[maxm*3],c1[maxn],c2[maxm*2];struct suan{    int l,r,x,y,k;} ask[maxm];struct dian{    int x,wz;} ld[maxm*2];int tree[maxn*4];int root[maxn],sum[maxtot],left[maxtot],right[maxtot];dian zf[maxm*2];int dl[maxn],d[maxm],fz[maxn];int a[maxn],b[maxn],ans[maxm],sta[80];bool bz[maxn*4],big[maxn*2],whe[maxm*2];int i,j,k,l,r,x,y,t,n,m,tot,top,cnt,num;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}int newnode(int x){    tot++;    left[tot]=left[x];    right[tot]=right[x];    sum[tot]=sum[x];    return tot;}void insert(int &x,int l,int r,int a){    x=newnode(x);    sum[x]++;    if (l==r) return;    int mid=(l+r)/2;    if (a<=mid) insert(left[x],l,mid,a);else insert(right[x],mid+1,r,a);}int find(int x,int y,int l,int r,int k){    if (l==r) return l;    int mid=(l+r)/2;    if (k<=sum[left[y]]-sum[left[x]]) return find(left[x],left[y],l,mid,k);    else return find(right[x],right[y],mid+1,r,k-(sum[left[y]]-sum[left[x]]));}void mark(int p){    tree[p]=0;    bz[p]=1;}void down(int p){    if (bz[p]){        mark(p*2);        mark(p*2+1);        bz[p]=0;    }}void change(int p,int l,int r,int a){    tree[p]++;    if (l==r) return;    down(p);    int mid=(l+r)/2;    if (a<=mid) change(p*2,l,mid,a);else change(p*2+1,mid+1,r,a);}int query(int p,int l,int r,int a,int b){    if (!tree[p]) return 0;    if (l==a&&r==b) return tree[p];    int mid=(l+r)/2;    down(p);    if (b<=mid) return query(p*2,l,mid,a,b);    else if (a>mid) return query(p*2+1,mid+1,r,a,b);    else return query(p*2,l,mid,a,mid)+query(p*2+1,mid+1,r,mid+1,b);}bool cmp(dong a,dong b){    return a.wz<b.wz||a.wz==b.wz&&a.ca<b.ca;}void solve(int l,int r,int u,int v){    if (u>v) return;    int i,j;    if (l==r){        fo(i,u,v) ans[ld[i].x]=l;        return;    }    int mid=(l+r)/2,w,t;    top=0;    fo(i,l,r)         if (b[dl[i]]<=mid){            c1[++top].x=dl[i];            c1[top].ca=0;            c1[top].wz=dl[i];        }    num=0;    fo(i,u,v){        /*c[++cnt].x=ld[i];        c[cnt].ca=1;        c[cnt].wz=ask[ld[i]].l-1;        c[++cnt].x=ld[i];        c[cnt].ca=1;        c[cnt].wz=ask[ld[i]].r;*/        d[ld[i].x]=0;        c2[++num].x=ld[i].x;        c2[num].ca=1;        c2[num].wz=ld[i].wz;    }    //sort(c+1,c+cnt+1,cmp);    cnt=0;    i=j=1;    while (i<=top||j<=num){        if (i>top) c[++cnt]=c2[j++];        else if (j>num) c[++cnt]=c1[i++];        else if (c1[i].wz<=c2[j].wz) c[++cnt]=c1[i++];        else c[++cnt]=c2[j++];    }    bool czy=0;    fo(i,1,cnt)        if (c[i].ca==0) change(1,1,n,a[c[i].x]),czy|=1;        else{            if (!czy) continue;            t=query(1,1,n,ask[c[i].x].x,ask[c[i].x].y);            if (c[i].wz==ask[c[i].x].l-1) d[c[i].x]-=t;else d[c[i].x]+=t;        }    mark(1);    fo(i,u,v)        if (ask[ld[i].x].k<=d[ld[i].x]) whe[ld[i].x]=1;else whe[ld[i].x]=0;    w=u-1;    fo(i,u,v)        if (whe[ld[i].x]) zf[++w]=ld[i];    t=w;    fo(i,u,v)        if (!whe[ld[i].x]){            if (ld[i].wz==ask[ld[i].x].r) ask[ld[i].x].k-=d[ld[i].x];            zf[++t]=ld[i];        }    fo(i,u,v) ld[i]=zf[i];    t=l-1;    fo(i,l,r)        if (b[dl[i]]<=mid) fz[++t]=dl[i];    fo(i,l,r)        if (b[dl[i]]>mid) fz[++t]=dl[i];    fo(i,l,r) dl[i]=fz[i];    solve(l,mid,u,w);    solve(mid+1,r,w+1,v);}void write(int x){    if (!x){        putchar('0');        putchar('\n');        return;    }    top=0;    while (x){        sta[++top]=x%10;        x/=10;    }    while (top) putchar('0'+sta[top--]);    putchar('\n');}bool cmp1(dian a,dian b){    return a.wz<b.wz;}int main(){    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);    n=read();    fo(i,1,n) a[i]=read();    fo(i,1,n) b[i]=read();    fo(i,1,n){        root[i]=root[i-1];        insert(root[i],1,n,a[i]);    }    m=read();    fo(i,1,m){        l=read();r=read();x=read();y=read();k=read();        x=find(root[l-1],root[r],1,n,x);        y=find(root[l-1],root[r],1,n,y);        ask[i].l=l;ask[i].r=r;        ask[i].x=x;ask[i].y=y;        ask[i].k=k;    }    fo(i,1,n) dl[i]=i;    fo(i,1,m){        ld[i*2-1].x=ld[i*2].x=i;        ld[i*2-1].wz=ask[i].l-1;        ld[i*2].wz=ask[i].r;    }    sort(ld+1,ld+2*m+1,cmp1);    solve(1,n,1,2*m);    fo(i,1,m) write(ans[i]);}
原创粉丝点击