【JZOJ5296】【清華集訓2017模擬】Sequence

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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章