【JZOJ5296】【清华集训2017模拟】Sequence

来源:互联网 发布:java导出excel表格方法 编辑:程序博客网 时间:2024/06/05 00:08

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

对于S和S’,我们可以用主席树很轻松的求出,但不能求出二关键字的k大。所以我们考虑整体二分。我们可以求出排名在[x,y]内的元素的范围[a,b]。对于一个范围[l,r]设满足排名k在该区间的询问[x,y],我们二分出mid,对于一个询问,若满足区间[l,r]内第一关键字在[a,b]且满足第二关键字小于mid的数量少于k,则答案一定在[l,mid]内。因为满足区间[l,r]内因为第二关键字是排列,我们将第二关键字在[l,mid]内的元素按位置排序,并将询问拆成[1,l-1],[1,r]两个询问,然后维护一个指针时期插入的数的位置小于询问,将第一关键字插入至树状数组查询即可。时间复杂度O(Nlog2N)。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int maxn=3e4+5,maxn1=2e5+5;struct code{    int l,r,num;}f[maxn*20];struct code2{    int x,id;}c[maxn]; struct code1{    int l,r,x,y,k,id;}q[maxn1],q1[maxn1];int a[maxn1],b[maxn1],d[maxn1],ans[maxn1],g[maxn1];int n,m,i,t,j,k,l,x,y,z,num;bool cmp(code2 x,code2 y){    return x.x<y.x;}bool cmp1(code2 x,code2 y){    return x.id<y.id;}bool cmp2(code1 x,code1 y){    return x.l<y.l;}void insert(int l,int r,int &v,int x){    int mid=(l+r)/2;    f[++num]=f[v];v=num;f[v].num++;    if (l==r) return;    if (mid>=x) insert(l,mid,f[v].l,x);    else insert(mid+1,r,f[v].r,x);}void find(int l,int r,int v,int v1,int x){    int mid=(l+r)/2;    if (l==r){        t=l;return;    }    if (x>f[f[v].l].num-f[f[v1].l].num) find(mid+1,r,f[v].r,f[v1].r,x-(f[f[v].l].num-f[f[v1].l].num));    else find(l,mid,f[v].l,f[v1].l,x);}void insert1(int x,int z){    while (x<=n) g[x]+=z,x+=(x&(-x));}int find1(int x){    int t=0;    while (x>0) t+=g[x],x-=(x&(-x));    return t;}void dg(int l,int r,int x,int y){    int mid=(l+r)/2;    if (x>y) return;    if (l==r){        for (i=x;i<=y;i++)            ans[q[i].id]=l;        return;    }    sort(c+l,c+mid+1,cmp1);    num=0;    for (i=x;i<=y;i++){        q1[++num]=q[i];q1[++num]=q[i];q1[num-1].l--;        q1[num].l=q[i].r;q1[num-1].r=-1;q1[num].r=1;    }    sort(q1+1,q1+num+1,cmp2);j=l;    for (i=1;i<=num;i++){        while (c[j].id<=q1[i].l && j<=mid) insert1(a[c[j++].id],1);        d[q1[i].id]+=(find1(q1[i].y)-find1(q1[i].x-1))*q1[i].r;    }j--;    while (j>=l)         insert1(a[c[j--].id],-1);    int num=0;    for (i=x;i<=y;i++)        if (ans[q[i].id]+d[q[i].id]>=q[i].k) q1[++num]=q[i];    int t=num;    for (i=x;i<=y;i++)        if (ans[q[i].id]+d[q[i].id]<q[i].k) q1[++num]=q[i],ans[q[i].id]+=d[q[i].id];    for (i=x;i<=y;i++)q[i]=q1[i-x+1],d[q[i].id]=0;    sort(c+l,c+mid+1,cmp);    dg(l,mid,x,x+t-1);dg(mid+1,r,x+t,y);}int main(){    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);    scanf("%d",&n);    for (i=1;i<=n;i++)        scanf("%d",&a[i]),d[i]=d[i-1],insert(1,n,d[i],a[i]);    for (i=1;i<=n;i++)scanf("%d",&b[i]),c[i].x=b[i],c[i].id=i;    sort(c+1,c+n+1,cmp);    scanf("%d",&m);    for (i=1;i<=m;i++){        scanf("%d%d%d%d%d",&q[i].l,&q[i].r,&x,&y,&q[i].k);q[i].id=i;        t=0;find(1,n,d[q[i].r],d[q[i].l-1],x);q[i].x=t;        t=0;find(1,n,d[q[i].r],d[q[i].l-1],y);q[i].y=t;    }    memset(d,0,sizeof(d));    dg(1,n,1,m);    for (i=1;i<=m;i++) printf("%d\n",ans[i]);}
原创粉丝点击