• [bzoj3110][Zjoi2013]K大数查询


    来自FallDream的博客,未经允许,请勿转载,谢谢。


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

    如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。n,m<=50000

    这道题数据结构随便切吧 什么树套树之类的

    学习一下整体二分,写了个模板,查询线段树/树状数组。整体二分啥具体的可以自行百度,不难理解吧..

    但是感觉我写的好丑啊常数巨大

    #include<iostream>
    #include<cstdio>
    #define MN 50000
    #define INF 2147483647
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m;ll ans[MN+5];
    struct op{int kind,a,b;ll c;int id;}q[MN*60];
    struct Tree{int l,r;ll val,x;}T[MN*14+5];
    
    void pushdown(int x)
    {
        int l=x<<1,r=x<<1|1;
        T[l].x+=1LL*(T[l].r-T[l].l+1)*T[x].val;
        T[r].x+=1LL*(T[r].r-T[r].l+1)*T[x].val;
        T[l].val+=T[x].val;T[r].val+=T[x].val;
        T[x].val=0;
    }
    
    void build(int x,int l,int r)
    {
        if((T[x].l=l)==(T[x].r=r)) return;
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
    }
    
    void renew(int x,int l,int r,int ad)
    {
        if(T[x].l==l&&T[x].r==r)
        {
            T[x].x+=1LL*(r-l+1)*ad;
            T[x].val+=ad;return;
        }
        if(T[x].val) pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) renew(x<<1,l,r,ad);
        else if(l>mid) renew(x<<1|1,l,r,ad);
        else renew(x<<1,l,mid,ad),renew(x<<1|1,mid+1,r,ad);
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
    
    ll query(int x,int l,int r)
    {
        if(T[x].l==l&&T[x].r==r) return T[x].x;
        if(T[x].val) pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) return query(x<<1,l,r);
        else if(l>mid) return query(x<<1|1,l,r);
        else return query(x<<1,l,mid)+query(x<<1|1,mid+1,r);
    }
    
    void solve(int lt,int rt,int l,int r)
    {
        if(l==r) 
        {
            for(int i=lt;i<=rt;i++) 
                if(q[i].kind>1) ans[q[i].id]=l;
            return;
        }
        int mid=((ll)l+(ll)r+1)>>1,beg=m+1;
        for(int i=lt;i<=rt;i++) if(q[i].kind>1) ans[q[i].id]=q[i].c+query(1,q[i].a,q[i].b);
        for(int i=lt;i<=rt;i++)
        {
            if(q[i].kind==1) q[i].c>=mid?(renew(1,q[i].a,q[i].b,1),q[++m]=q[i],0):0;
            else 
            {
                ans[q[i].id]-=query(1,q[i].a,q[i].b);
                if(ans[q[i].id]<=0) q[++m]=q[i];
                else q[i].c=ans[q[i].id];
            }
        }
        int ed=m;
        for(int i=lt;i<=rt;i++)
            if((ans[q[i].id]>0&&q[i].kind>1)||(q[i].kind==1&&q[i].c<mid))
                q[++m]=q[i];
        int end=m;
        if(beg<=ed)solve(beg,ed,mid,r);
        if(end>ed) solve(ed+1,end,l,mid-1);
    }
    
    int main()
    {
        n=read();m=read();build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            q[i].kind=read();q[i].a=read();q[i].b=read();
            q[i].c=read();q[i].id=i;
        }
        int tot=m;
        solve(1,m,-INF,INF);
        for(int i=1;i<=tot;i++)if(q[i].kind==2)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    vue 兄弟组件间传值(bus方式)的坑(重复触发和首次未触发)
    vue 组件间传值(兄弟)(bus方式)
    vue 导出数据到excel
    vue-cli webpack打包后加载资源的路径问题
    vue组件传值之(父子)
    vue组件传值
    thinkphp 5 一些常见问题
    windows 安装 composer
    HTML H5响应式,表格,表单等
    面试
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3110.html
Copyright © 2020-2023  润新知