1. 程式人生 > >【BZOJ2333】棘手的操作(左偏樹,STL)

【BZOJ2333】棘手的操作(左偏樹,STL)

ise 最大 pre mat line online continue inline lld

【BZOJ2333】棘手的操作(左偏樹,STL)

題面

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)