首页 > 代码库 > 3110: [Zjoi2013]K大数查询 树状数组套线段树

3110: [Zjoi2013]K大数查询 树状数组套线段树

3110: [Zjoi2013]K大数查询

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1384  Solved: 629
[Submit][Status]

Description

有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

Input

第一行N,M
接下来M行,每行形如1 a b c或2 a b c

Output

输出每个询问的结果

Sample Input

2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3

Sample Output

1
2
1

HINT

 



【样例说明】

第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

大的数是 1 。‍


N,M<=50000,N,M<=50000

a<=b<=N

1操作中abs(c)<=N

2操作中abs(c)<=Maxlongint

 

  这道题本来想用线段树套平衡树做,但是即便加了永久lazy标记,还是TLE了,后来改为树状数组套线段树,注意树状数组二分可优化为O(logn)

 

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define MAXT 8100000#define MAXN 51009#define lch (now<<1)#define rch (now<<1^1)#define INF 0x3f3f3f3f#define L(x) SBT[x].L#define R(x) SBT[x].R#define S(x) SBT[x].S#define val(x) SBT[x].val#define tot(x) SBT[x].tot#define sum(x) SBT[x].sumtypedef long long qword;int n,m;inline int nextInt(){        register int x=0;        register char ch;        while (ch=getchar(),ch<0||ch > 9);        do                x=x*10+ch-0;        while (ch=getchar(),ch<=9 && ch>=0);        return x;}int topt;struct SBT_T{        int L,R,S,val,tot,sum;}SBT[MAXT];inline void update(int now){        if (!now)return ;        S(now)=S(L(now))+S(R(now))+1;        sum(now)=sum(L(now))+sum(R(now))+tot(now);}inline void l_rotate(int &now){        register int t=R(now);        R(now)=L(t);update(now);        L(t)=now;update(t);        now=t;}inline void r_rotate(int &now){        register int t=L(now);        L(now)=R(t);update(now);        R(t)=now;update(t);        now=t;}inline void maintain(int &now){        if (S(L(L(now)))>S(R(now)))        {                r_rotate(now);                //maintain(L(now));                maintain(R(now));                maintain(now);        }else if (S(R(R(now)))>S(L(now)))        {                l_rotate(now);                //maintain(R(now));                maintain(L(now));                maintain(now);        }else if (S(R(L(now)))>S(R(now)))        {                l_rotate(L(now));                r_rotate(now);                maintain(R(now));                maintain(L(now));                maintain(now);        }else if (S(L(R(now)))>S(L(now)))        {                r_rotate(R(now));                l_rotate(now);                maintain(R(now));                maintain(L(now));                maintain(now);        }}void Insert(int &now,int v,int t){        if (!now)        {                //        if (topt>MAXT-10)throw 1;                now=++topt;                L(now)=R(now)=0;                val(now)=v;                tot(now)=sum(now)=t;                return ;        }        if (v==val(now))                tot(now)+=t;        else if (v<val(now))                Insert(L(now),v,t);        else if (val(now)<v)                Insert(R(now),v,t);        update(now);        maintain(now);}/*int Get_tot(int &now,int v){        if (!now)return 0;        if (val(now)==v)                return sum(L(now));        else if (v<val(now))                return Get_tot(L(now),v);        else if (val(now)<v)                return Get_tot(R(now),v)+sum(L(now))+tot(now);        return 0;}*/int Get_tot(int now,int v){        int ret=0;        while (now && val(now)!=v)        {                if (v<val(now))                        now=L(now);                else if (val(now)<v)                        ret+=sum(L(now))+tot(now),now=R(now);        }        if (now && val(now)==v)ret+=sum(L(now));        return ret;}void Scan(int now){        if (!now)return ;        Scan(L(now));        printf("%d(%d) ",val(now),tot(now));        Scan(R(now));}struct sgt_node{        int l,r;        int rt;        int lazy;}sgt[MAXN*4];void Build_sgt(int now,int l,int r){        sgt[now].l=l;        sgt[now].r=r;        if (l==r)return ;        Build_sgt(lch,l,(l+r)>>1);        Build_sgt(rch,((l+r)>>1)+1,r);}void Add_val(int now,int l,int r,int v){        Insert(sgt[now].rt,v,r-l+1);        if (sgt[now].l==l && sgt[now].r==r)        {                Insert(sgt[now].lazy,v,1);                return ;        }        int mid=(sgt[now].l+sgt[now].r)>>1;        if (r<=mid)        {                Add_val(lch,l,r,v);        }else if (mid<l)        {                Add_val(rch,l,r,v);        }else        {                Add_val(lch,l,mid,v);                Add_val(rch,mid+1,r,v);        }}int Qry_tot(int now,int l,int r,int v){        int ret=0;        if (sgt[now].l==l && sgt[now].r==r)        {                return Get_tot(sgt[now].rt,v);        }        ret=Get_tot(sgt[now].lazy,v)*(r-l+1);        int mid=(sgt[now].l+sgt[now].r)>>1;        if (r<=mid)                ret+=Qry_tot(lch,l,r,v);        else if (mid<l)                ret+=Qry_tot(rch,l,r,v);        else                ret+=Qry_tot(lch,l,mid,v)+Qry_tot(rch,mid+1,r,v);        return ret;}int Get_size(int now,int l,int r){        if (sgt[now].l==l && sgt[now].r==r)        {                return sum(sgt[now].rt);        }        int mid=(sgt[now].l+sgt[now].r)>>1;        if (r<=mid)                return Get_size(lch,l,r) + sum(sgt[now].lazy)*(r-l+1);        else if (mid<l)                return Get_size(rch,l,r) + sum(sgt[now].lazy)*(r-l+1);        else                return Get_size(lch,l,mid)+Get_size(rch,mid+1,r) + sum(sgt[now].lazy)*(r-l+1);}int Qry_kth(int ll,int rr,int rk){        int l,r,mid;        l=-n;        r=n+1;        rk=Get_size(1,ll,rr)-rk;        int t=0;        if (rk<0)return 1;        while (l+1<r)        {                mid=(l+r)/2;                t=Qry_tot(1,ll,rr,mid);                if (t<=rk)                        l=mid;                else                        r=mid;        }        return l;}int main(){        freopen("input.txt","r",stdin);        freopen("output.txt","w",stdout);        int i,j,k,x,y,z;        int rt=0;        scanf("%d%d",&n,&m);        int opt;        Build_sgt(1,1,n);        for (i=0;i<m;i++)//50000        {                opt=nextInt();                x=nextInt();                y=nextInt();                z=nextInt();                //scanf("%d%d%d%d",&opt,&x,&y,&z);                if (opt==1)                {                        Add_val(1,x,y,z);                }else                {                        printf("%d\n",Qry_kth(x,y,z));                }        }}
线段树+SBT
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define MAXN 101000#define MAXT 28000000#define lowbit(x) (x&(-x))inline int nextInt(){        register int x=0;        register char ch;        while (ch=(char)getchar(),ch<0||ch > 9);        do                x=x*10+ch-0;        while (ch=(char)getchar(),ch<=9 && ch>=0);        return x;}int n,m;struct sgt_node{        int lch,rch;        int t,lazy;}sgt[MAXT];int topt=0;void Add_sgt(int &now,int l,int r,int x,int y){        if (!now)        {                now=++topt;                sgt[now].t=sgt[now].lazy=0;        }        if (l==x && r==y)        {                sgt[now].t+=r-l+1;                sgt[now].lazy++;                return ;        }        int mid=(l+r)>>1;        if (sgt[now].lazy)        {                if (!sgt[now].lch)                        sgt[now].lch=++topt;                if (!sgt[now].rch)                        sgt[now].rch=++topt;                sgt[sgt[now].lch].lazy+=sgt[now].lazy;                sgt[sgt[now].rch].lazy+=sgt[now].lazy;                sgt[sgt[now].lch].t+=sgt[now].lazy*(mid-l+1);                sgt[sgt[now].rch].t+=sgt[now].lazy*(r-mid);                sgt[now].lazy=0;        }        if (y<=mid)        {                Add_sgt(sgt[now].lch,l,mid,x,y);        }else if (mid<x)        {                Add_sgt(sgt[now].rch,mid+1,r,x,y);        }else        {                Add_sgt(sgt[now].lch,l,mid,x,mid);                Add_sgt(sgt[now].rch,mid+1,r,mid+1,y);        }        sgt[now].t=sgt[sgt[now].lch].t+sgt[sgt[now].rch].t;}int Qry_sgt(int &now,int l,int r,int x,int y){        if (!now || sgt[now].t==0)return 0;        if (l==x && r==y)                return sgt[now].t;        int mid=(l+r)>>1;        if (sgt[now].lazy)        {                if (!sgt[now].lch)                        sgt[now].lch=++topt;                if (!sgt[now].rch)                        sgt[now].rch=++topt;                sgt[sgt[now].lch].lazy+=sgt[now].lazy;                sgt[sgt[now].rch].lazy+=sgt[now].lazy;                sgt[sgt[now].lch].t+=sgt[now].lazy*(mid-l+1);                sgt[sgt[now].rch].t+=sgt[now].lazy*(r-mid);                sgt[now].lazy=0;        }        if (y<=mid)        {                return Qry_sgt(sgt[now].lch,l,mid,x,y);        }else if (mid<x)        {                return Qry_sgt(sgt[now].rch,mid+1,r,x,y);        }else        {                return Qry_sgt(sgt[now].lch,l,mid,x,mid)                        +Qry_sgt(sgt[now].rch,mid+1,r,mid+1,y);        }}int tarr2[MAXN],tarr3[MAXN];void Add_tarr2(int l,int r){        r++;        int a=r;        while (r<MAXN)        {                tarr2[r]--;                tarr3[r]-=a;                r+=lowbit(r);        }        a=l;        while (l<MAXN)        {                tarr2[l]++;                tarr3[l]+=a;                l+=lowbit(l);        }}//segma((n-i+1)*a[i])//=(n+1)*segma(a[i]) - segma(i*a[i])int Qry_tarr2(int l,int r){        int ret=0;        int v1,v2;        int now;        v1=0;        l--;        now=r;        v1=v2=0;        while (now)        {                v1+=tarr2[now];                v2+=tarr3[now];                now-=lowbit(now);        }        ret+=v1*(r+1)-v2;        now=l;        v1=v2=0;        while (now)        {                v1+=tarr2[now];                v2+=tarr3[now];                now-=lowbit(now);        }        ret-=v1*(l+1)-v2;        return ret;}int tarr[MAXN];void Add_tarr(int pos,int l,int r){        pos+=n+1;        Add_tarr2(l,r);        while (pos<MAXN)        {                Add_sgt(tarr[pos],0,n+1,l,r);                pos+=lowbit(pos);        }}/*int Qry_tarr(int rk,int ll,int rr){        int now=0,t;        int i;        int l,r,mid;        rk=Qry_tarr2(ll,rr)-rk+1;        l=-n-1;r=n+1;        while (l+1<r)        {                t=0;                mid=(l+r)>>1;                now=mid+n+1;                while (now)                {                        t+=Qry_sgt(tarr[now],0,n+1,ll,rr);                        now-=lowbit(now);                }                if (t<rk)                        l=mid;                else                         r=mid;        }        return r==-n ? 1 : r;}*/int Qry_tarr(int rk,int ll,int rr){        int now=0,t;        int i;        int l,r,mid;        rk=Qry_tarr2(ll,rr)-rk+1;        for (i=20;i>=0;i--)        {                if (now+(1<<i)<MAXN && (t=Qry_sgt(tarr[now+(1<<i)],0,n+1,ll,rr))<rk)                {                        rk-=t;                        now+=(1<<i);                }        }        now=now+1-(n+1);        return now;}int main(){        freopen("input.txt","r",stdin);        freopen("output.txt","w",stdout);        scanf("%d%d",&n,&m);        int i;        int opt,x,y,z;        for (i=0;i<m;i++)        {                opt=nextInt();                x=nextInt();                y=nextInt();                z=nextInt();                //scanf("%d%d%d%d",&opt,&x,&y,&z);                if (opt==1)                {                        Add_tarr(z,x,y);                }else                {                        printf("%d\n",Qry_tarr(z,x,y));                }        }}
树状数组+线段树

 

3110: [Zjoi2013]K大数查询 树状数组套线段树