[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\n",ans[i]);
    return 0;
}

 

posted @ 2017-04-19 21:44  FallDream  阅读(164)  评论(0编辑  收藏  举报