• bzoj3110 [Zjoi2013]K大数查询


    题目描述

    题解:

    看不懂样例的dalao看这里:

    每个位置加入一个数c指的是插入,一个位置上可以有很多数

    整体二分。

    将修改和询问放在一起,然后二分值域,每次有询问时判断$k$和$sum[l,r]$的大小。

    最后保证$[l,l]$时$k$减成$0$即可。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 50050
    #define ll long long
    inline ll rd()
    {
        ll f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        return f*c;
    }
    ll n,m,cnt;
    ll ans[N],to[N];
    struct str
    {
        ll opt,a,b,id;
        ll c;
    }p[N],tmpl[N],tmpr[N];
    ll tot;
    struct Pair
    {
        ll x;ll id;
        Pair(){}
        Pair(ll x,ll i):x(x),id(i){}
    }pr[N];
    bool cmp(Pair a,Pair b)
    {
        return a.x<b.x;
    }
    struct segtree
    {
        ll siz[N<<2],vl[N<<2],tag[N<<2];
        bool rec[N<<2];
        void add(ll u,ll d)
        {
            tag[u]+=d;
            vl[u]+=siz[u]*d;
        }
        void rece(ll u)
        {
            rec[u]=1;
            vl[u]=tag[u]=0;
        }
        void update(ll u)
        {
            vl[u] = vl[u<<1]+vl[u<<1|1];
        }
        void build(ll l,ll r,ll u)
        {
            siz[u] = r-l+1;
            if(l==r)return ;
            ll mid = (l+r)>>1;
            build(l,mid,u<<1);
            build(mid+1,r,u<<1|1);
        }
        void init()
        {
            build(1,n,1);
        }
        void pushdown(ll u)
        {
            if(rec[u])
            {
                rece(u<<1);
                rece(u<<1|1);
                rec[u]=0;
            }
            if(tag[u])
            {
                add(u<<1,tag[u]);
                add(u<<1|1,tag[u]);
                tag[u]=0;
            }
        }
        void insert(ll l,ll r,ll u,ll ql,ll qr,ll d)
        {
            if(l==ql&&r==qr)
            {
                add(u,d);
                return ;
            }
            pushdown(u);
            ll mid = (l+r)>>1;
            if(qr<=mid)insert(l,mid,u<<1,ql,qr,d);
            else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d);
            else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d);
            update(u);
        }
        ll query(ll l,ll r,ll u,ll ql,ll qr)
        {
            if(l==ql&&r==qr)return vl[u];
            pushdown(u);
            ll mid = (l+r)>>1;
            if(qr<=mid)return query(l,mid,u<<1,ql,qr);
            else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
            else return query(l,mid,u<<1,ql,mid)+query(mid+1,r,u<<1|1,mid+1,qr);
        }
    }tr;
    void divi(ll l,ll r,ll beg,ll ens)
    {
        if(beg>ens)return ;
        if(l==r)
        {
            for(ll i=beg;i<=ens;i++)
                ans[p[i].id] = to[l];
            return ;
        }
        ll mid = (l+r)>>1;
        ll lt = 0,rt = 0;
        tr.rece(1);
        bool l1=0,r1=0;
        for(ll i=beg;i<=ens;i++)
        {
            if(p[i].opt==1)
            {
                if(p[i].c<=mid)
                {
                    tmpl[++lt] = p[i];
                }else
                {
                    tr.insert(1,n,1,p[i].a,p[i].b,1);
                    tmpr[++rt] = p[i];
                }
            }else
            {
                ll now = tr.query(1,n,1,p[i].a,p[i].b);
                if(now<p[i].c)
                {
                    p[i].c-=now;
                    tmpl[++lt] = p[i];
                    l1=1;
                }else
                {
                    tmpr[++rt] = p[i];
                    r1=1;
                }
            }
        }
        for(ll i=beg;i<=beg+lt-1;i++)p[i]=tmpl[i-beg+1];
        for(ll i=beg+lt;i<=ens;i++)p[i]=tmpr[i-beg-lt+1];
        if(l1)divi(l,mid,beg,beg+lt-1);
        if(r1)divi(mid+1,r,beg+lt,ens);
    }
    int main()
    {
    //    freopen("tt.in","r",stdin);
    //    freopen("tt.out","w",stdout);
        n = rd(),m = rd();
        for(ll i=1;i<=m;i++)
        {
            p[i].opt = rd(),p[i].a = rd(),p[i].b = rd(),p[i].c = rd();
            if(p[i].opt==2)
            {
                p[i].id = ++cnt;
            }else
            {
                pr[++tot] = Pair(p[i].c,i);
            }
        }
        sort(pr+1,pr+1+tot,cmp);
        ll las = 100005;ll k = 0;
        for(ll i=1;i<=tot;i++)
        {
            if(las!=pr[i].x)
            {
                las = pr[i].x;
                k++;to[k]=las;
            }
            p[pr[i].id].c = k;
        }
        tr.init();
        divi(1,k,1,m);
        for(ll i=1;i<=cnt;i++)
            printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    verilog编码规范
    verilog代码 想法验证---与寄存器输出有关
    MMCM与PLL
    Vivado约束文件(XDC)的探究(2)
    Vivado约束文件(XDC)的探究(1)
    VGA图像显示组成模块分析
    关于Quad PLL /CPLL参考时钟的选择
    GTX的生成(包括COMMON)
    SD-SDI播出系统---使用GTX TX产生恢复时钟
    DRP端口描述
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10201429.html
Copyright © 2020-2023  润新知