1251. 序列終結者【平衡樹-splay】
阿新 • • 發佈:2018-03-31
gpo name blog swap push cpp turn AC ace
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Description
網上有許多題,就是給定一個序列,要你支持幾種操作:A、B、C、D。一看另一道題,又是一個序列 要支持幾種操作:D、C、B、A。尤其是我們這裏的某人,出模擬試題,居然還出了一道這樣的,真是沒技術含量……這樣 我也出一道題,我出這一道的目的是為了讓大家以後做這種題目有一個“庫”可以依靠,沒有什麽其他的意思。這道題目 就叫序列終結者吧。 【問題描述】 給定一個長度為N的序列,每個序列的元素是一個整數(廢話)。要支持以下三種操作: 1. 將[L,R]這個區間內的所有數加上V。 2. 將[L,R]這個區間翻轉,比如1 2 3 4變成4 3 2 1。 3. 求[L,R]這個區間中的最大值。 最開始所有元素都是0。
Input
第一行兩個整數N,M。M為操作個數。 以下M行,每行最多四個整數,依次為K,L,R,V。K表示是第幾種操作,如果不是第1種操作則K後面只有兩個數。
Output
對於每個第3種操作,給出正確的回答。
Sample Input
4 41 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【數據範圍】
N<=50000,M<=100000。
splay區間操作模板
#include<iostream> #include<cstring> #include<cstdio> #include<map> #define MAXN (1000000+10) using namespace std; int Father[MAXN]; int Son[MAXN][2]; int Key[MAXN]; int Size[MAXN]; int Root,sz,n,m; int Max[MAXN],Val[MAXN],Add[MAXN],Rev[MAXN]; using namespace std; inline int Get(int x) { return Son[Father[x]][1]==x; } inline void Update(int x) { Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1; Max[x]=max(Val[x],max(Max[Son[x][0]],Max[Son[x][1]])); } inline void Pushdown(int x) { if (Add[x]) { if (Son[x][0]) { Max[Son[x][0]]+=Add[x]; Val[Son[x][0]]+=Add[x]; Add[Son[x][0]]+=Add[x]; } if (Son[x][1]) { Max[Son[x][1]]+=Add[x]; Val[Son[x][1]]+=Add[x]; Add[Son[x][1]]+=Add[x]; } Add[x]=0; } if (Rev[x]) { Rev[x]=0; swap(Son[x][0],Son[x][1]); Rev[Son[x][0]]^=1; Rev[Son[x][1]]^=1; } } inline void Rotate(int x) { Pushdown(Father[x]); Pushdown(x); int wh=Get(x); int fa=Father[x],fafa=Father[fa]; Son[fa][wh]=Son[x][wh^1]; Father[fa]=x; if (Son[fa][wh]) Father[Son[fa][wh]]=fa; Son[x][wh^1]=fa; Father[x]=fafa; if (fafa) Son[fafa][Son[fafa][1]==fa]=x; Update(fa); Update(x); } inline void Splay(int x,int tar) { for (int fa;(fa=Father[x])!=tar;Rotate(x)) if (Father[fa]!=tar) Rotate(Get(fa)==Get(x)?fa:x); if (!tar) Root=x; } void Build(int l,int r,int fa) { if (l>r) return; if (l==r) { Size[l]=1; Father[l]=fa; Son[fa][l>fa]=l; return; } int mid=(l+r)>>1; Build(l,mid-1,mid); Build(mid+1,r,mid); Father[mid]=fa; Son[fa][mid>fa]=mid; Update(mid); } int Findx(int x) { int now=Root; while (1) { Pushdown(now); if (Size[Son[now][0]]>=x) now=Son[now][0]; else { x-=Size[Son[now][0]]; if (x==1) { Splay(now,0); return now; } x--; now=Son[now][1]; } } } inline int Split(int x,int y) { int xx=Findx(x),yy=Findx(y); Splay(xx,0); Splay(yy,xx); return Son[yy][0]; } int main() { int p,l,r,x; scanf("%d%d",&n,&m); Build(1,n+2,0); Root=(n+3)>>1; Max[0]=-0x7fffffff; for (int i=1;i<=m;++i) { scanf("%d",&p); if (p==1) { scanf("%d%d%d",&l,&r,&x); int node=Split(l,r+2); Val[node]+=x; Max[node]+=x; Add[node]+=x; } if (p==2) { scanf("%d%d",&l,&r); int node=Split(l,r+2); Rev[node]^=1; } if (p==3) { scanf("%d%d",&l,&r); int node=Split(l,r+2); printf("%d\n",Max[node]); } } }
1251. 序列終結者【平衡樹-splay】