您的位置:首页 > 其它

[bzoj3110][Zjoi2013]K大数查询

2017-04-19 21:44 323 查看
来自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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: