来自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; }