题目大意:
有n个位置,m个操作,提供下列两种操作:
1.在[x,y]区间内每个位置插入一个z
2.查询[x,y]区间内的第k大
注意是第k大不是第k小
来一段《树套树之歌》吧:
树套树 树套树 树套树套树 树套树树套树套树 树套树套树套树套树 树套树树套树套树 树套树套树套树套树套树
BGM:《邮递马车》
树套树摆在这里 关键是怎么套 我一开始想的是权值线段树在内层 结果外层的话树状数区间修改+查询忘记怎么写了 线段树压根不会可持久化标记 最后只能权值线段树开在外面
权值线段树开在外面 内层是区间线段树 记录该权值的覆盖区域
蒟蒻伤不起啊。。。。
注意这道题的内存空间很不充裕 所以节点能不开就不开 省掉内存就是胜利
把y写成r WA了一下午。。。。。 40%达成 我看来是写不完十道题了。。。。
写完之后无论时间还是空间都和Rank上的神犇们差很远 看来我还是去学线段树可持久化标记吧。。。
此外这题虽然说abs(c)<=n 但是c都是正整数 不用担心了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,m; struct Tree{ Tree *ls,*rs; unsigned int num,mark; Tree() { ls=rs=0x0; num=mark=0; } void add(int x,int y,unsigned int z) { num+=(y-x+1)*z; mark+=z; } void update(int x,int y,int l,int r) { int mid=x+y>>1; if(x==l&&y==r) { add(x,y,1u); return ; } if(!ls)ls=new Tree; if(!rs)rs=new Tree; if(mark) { ls->add(x,mid,mark); rs->add(mid+1,y,mark); mark=0; } if(r<=mid) ls->update(x,mid,l,r); else if(l>mid) rs->update(mid+1,y,l,r); else ls->update(x,mid,l,mid),rs->update(mid+1,y,mid+1,r); num=ls->num+rs->num; } unsigned int getans(int x,int y,int l,int r) { int mid=x+y>>1; if(!num) return 0; if(x==l&&y==r) return num; if(!ls)ls=new Tree; if(!rs)rs=new Tree; if(mark) { ls->add(x,mid,mark); rs->add(mid+1,y,mark); mark=0; } if(r<=mid) return ls->getans(x,mid,l,r); if(l>mid) return rs->getans(mid+1,y,l,r); return ls->getans(x,mid,l,mid) + rs->getans(mid+1,y,mid+1,r); } }; struct abcd{ abcd *ls,*rs,; Tree *tree; abcd() { ls=rs=0x0; tree=new Tree; } void update(int x,int y,int l,int r,int val) { int mid=x+y>>1; tree->update(1,n,l,r); if(x==y) return ; if(!ls)ls=new abcd; if(!rs)rs=new abcd; if(val<=mid) ls->update(x,mid,l,r,val); else rs->update(mid+1,y,l,r,val); } int getans(int x,int y,int l,int r,int k) { int mid=x+y>>1; if(x==y) return mid; if(!ls)ls=new abcd; if(!rs)rs=new abcd; int r_sum=rs->tree->getans(1,n,l,r); if(k>r_sum) return ls->getans(x,mid,l,r,k-r_sum); else return rs->getans(mid+1,y,l,r,k); } }root; int main() { //freopen("sequence.in","r",stdin); //freopen("sequence.out","w",stdout); int i,p,x,y,z; cin>>n>>m; for(i=1;i<=m;i++) { scanf("%d%d%d%d",&p,&x,&y,&z); if(p==1) root.update(1,n,x,y,z); else printf("%d\n", root.getans(1,n,x,y,z) ); } }