【BZOJ2333】棘手的操作(左偏树,STL)
2018-01-12 20:48
387 查看
题面
BZOJ上看把。。。题解
正如这题的题号我只能2333
神TM棘手的题目。。。
前面的单点/联通块操作
很显然是一个左偏树+标记
(确实很显然,只是写死人。。。)
然后对于全局的最大值而言
搞一个multi来水
看起来真的简单。。
写起来真的想死。。。
记住:要特判一下已经联通的块就不要再去Merge了
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 300010 inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int n; multiset<int> S; struct Node { int ls,rs,ff; int v,dis; int lz; }t[MAX]; int Lazy,root; int getf(int x){while(t[x].ff)x=t[x].ff;return x;} void putlazy(int x,int w) { t[x].v+=w; t[x].lz+=w; } void pushdown(int x) { if(!t[x].lz)return; if(t[x].ls)putlazy(t[x].ls,t[x].lz); if(t[x].rs)putlazy(t[x].rs,t[x].lz); t[x].lz=0; } int Merge(int r1,int r2) { if(!r1||!r2)return r1+r2; pushdown(r1);pushdown(r2); if(t[r1].v<t[r2].v)swap(r1,r2); t[r1].rs=Merge(t[r1].rs,r2); t[t[r1].rs].ff=r1; if(t[t[r1].ls].dis<t[t[r1].rs].dis)swap(t[r1].ls,t[r1].rs); t[r1].dis=t[t[r1].rs].dis+1; return r1; } void Update(int x) { if(!x)return; if(t[t[x].ls].dis<t[t[x].rs].dis)swap(t[x].ls,t[x].rs); t[x].dis=t[t[x].rs].dis+1; Update(t[x].ff); } void Alldown(int x) { if(t[x].ff)Alldown(t[x].ff); pushdown(x); } void Del(int x) { Alldown(x); t[t[x].ls].ff=t[t[x].rs].ff=0; if(t[t[x].ff].rs==x)t[t[x].ff].rs=0; else t[t[x].ff].ls=0; int rtt=getf(t[x].ff); Merge(rtt,Merge(t[x].ls,t[x].rs)); Update(t[x].ff); t[x].ff=t[x].ls=t[x].rs=0; } void Plus(int x,int w)//单点修改 { int rtt=getf(x); if(!t[x].ff) { S.erase(S.find(t[x].v)); t[t[x].ls].ff=t[t[x].rs].ff=0; pushdown(x),rtt=Merge(t[x].ls,t[x].rs); t[x].ff=t[x].ls=t[x].rs=0; } else Del(x),S.erase(S.find(t[rtt].v)); t[x].v+=w; int gg=Merge(x,rtt); S.insert(t[gg].v); } void AllPlus(int x,int w) { x=getf(x); S.erase(S.find(t[x].v)); putlazy(x,w); S.insert(t[x].v); } int main() { n=read(); for(int i=1;i<=n;++i)t[i].v=read(),S.insert(t[i].v); int Q=read(); char ch[5]; while(Q--) { scanf("%s",ch); if(ch[0]=='A') { if(ch[1]=='1') { int x=read(),v=read(); Plus(x,v); } else if(ch[1]=='2') { int x=read(),v=read(); AllPlus(x,v); } else Lazy+=read(); } else if(ch[0]=='F') { if(ch[1]=='1') { int x=read(); Alldown(x); printf("%d\n",t[x].v+Lazy); } else if(ch[1]=='2') { int x=read(); x=getf(x); printf("%d\n",t[x].v+Lazy); } else printf("%d\n",*--S.end()+Lazy); } else { int x=read(),y=read(); x=getf(x),y=getf(y); if(x==y)continue; int kk=Merge(x,y); S.erase(S.find(kk==x?t[y].v:t[x].v)); } } return 0; }
相关文章推荐
- 【BZOJ2333】棘手的操作(左偏树,STL)
- 【左偏树】【bzoj 2333】: [SCOI2011]棘手的操作
- 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树|可并堆-左偏树)
- 【BZOJ】2333: [SCOI2011]棘手的操作
- 【bzoj2333】 [SCOI2011]棘手的操作 可并堆+lazy标记
- BZOJ 2333: [SCOI2011]棘手的操作
- bzoj 2333: [SCOI2011]棘手的操作 离线+线段树
- [BZOJ2333][SCOI2011][可并堆]棘手的操作
- 【bzoj2333】[SCOI2011]棘手的操作 可并堆+set
- BZOJ 2333 SCOI2011 棘手的操作 可并堆套可并堆
- (右偏树)Bzoj2333: [SCOI2011]棘手的操作
- (右偏树)Bzoj2333: [SCOI2011]棘手的操作
- 【BZOJ2333】【SCOI2011】棘手的操作
- [bzoj2333][SCOI2011][棘手的操作]
- bzoj 2333 棘手的操作(线段树)
- BZOJ 2333 SCOI 2011 棘手的操作 可并堆
- 【bzoj2333】 SCOI2011—棘手的操作
- 【bzoj2333】[SCOI2011]棘手的操作 可并堆+STL-set
- [bzoj2333] [SCOI2011]棘手的操作 (可并堆)
- BZOJ 2333 [SCOI2011]棘手的操作