zoukankan      html  css  js  c++  java
  • bzoj 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].sum
    typedef 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
    ",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
    ",Qry_tarr(z,x,y));
                    }
            }
    }
    树状数组+线段树
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    单一职责原则
    23种设计模式
    微信小程序页面跳转
    【论文阅读】OrigamiNet:Weakly-Supervised, Segmentation-Free, One-Step, Full Page Text Recognition by learning to unfold
    【华为昇腾】DB_ResNet精度调优 Siammask性能调优 模型众筹项目复盘
    Ueditor 防止html过滤标签的操作
    海康摄像机rtsp地址格式官方最新版(2020)
    HLS协议解析
    解决帝国标题颜色颜色单引号问题
    帝国CMS动态页支持栏目导航标签,万能标签,循环子栏目标签
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4096010.html
Copyright © 2011-2022 走看看