平衡树裸题,这是新的平衡树模板。
平衡树,区间加值,区间翻转,区间查询最小值。
要时刻记住维护标记哦~
WA了好几次,对拍了一百多组数据,发现有两个操作没有更新信息。
我还是太年轻了。。。too young too simple。。。
#include<map>
#include<queue>
#include<stack>
#include<utility>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>
#define Mp(x,y) std::make_pair(x,y)
#define L(x) b[x].c[0]
#define R(x) b[x].c[1]
#define Fa(x) b[x].fa
#define Clear(x) b[x] = emp
const int MAXN = 100005, SIZE = 200005 , INF = (1LL<<31)-1;
int n , m;
int a[MAXN] = {0};
struct TreeNode
{
int c[2],fa,cnt;
int min,val;
int add,rev;
}b[SIZE] = {0}, emp = {0};
int root, size , blen;
int NewNode(int val)
{
++blen, b[blen].cnt = 1;
b[blen].min = b[blen].val = val;
return blen;
}
void PushDown(int x)
{
if(b[x].rev)
{
std::swap(L(x),R(x));
if(L(x)) b[L(x)].rev ^= 1;
if(R(x)) b[R(x)].rev ^= 1;
b[x].rev = 0;
}
if(b[x].add)
{
if(L(x)) b[L(x)].add += b[x].add, b[L(x)].val += b[x].add, b[L(x)].min += b[x].add;
if(R(x)) b[R(x)].add += b[x].add, b[R(x)].val += b[x].add, b[R(x)].min += b[x].add;
b[x].add = 0;
}
}
void Update(int x)
{
b[x].cnt = b[L(x)].cnt + b[R(x)].cnt + 1 , b[x].min = b[x].val;
if(L(x)) b[x].min = std::min(b[x].min,b[L(x)].min);
if(R(x)) b[x].min = std::min(b[x].min,b[R(x)].min);
}
void Rotate(int x,int &k)
{
int y = Fa(x) , z = Fa(y);
PushDown(y), PushDown(x);
int i = (R(y) == x) ,j = i^1 , fi = (R(z) == y);
if(y != k) b[z].c[fi] = x;else k = x;
Fa(x) = z,Fa(y) = x ,Fa(b[x].c[j]) = y;
b[y].c[i] = b[x].c[j], b[x].c[j] = y ;
Update(y), Update(x);
}
void Splay(int x,int &k)
{
PushDown(x);
while(x != k)
{
int y = Fa(x), z = Fa(y);
if(y != k)
{
if((y==R(z))^(x==R(y)))Rotate(x,k);
else Rotate(y,k);
}
Rotate(x,k);
}
Update(x);
return;
}
int Find(int p)
{
int pos = root;
while(1)
{
PushDown(pos);
int lc = b[L(pos)].cnt + 1;
if(p == lc) break;
else if(p < lc) pos = L(pos);
else { p -= lc ,pos = R(pos);}
}
return pos;
}
int GetInveral(int l,int r)
{
if(l == 1 && r == size)
return root;
else if(l == 1)
{
Splay(Find(r+1),root);
return L(root);
}
else if(r == size)
{
Splay(Find(l-1),root);
return R(root);
}
else
{
Splay(Find(l-1),root);
Splay(Find(r+1),R(root));
return L(R(root));
}
}
void Insert(int x,int p)
{
int pos = NewNode(p);
if(!size) root = pos;
else
{
Splay(Find(x),root);
if(x == size)
{
R(root) = pos, Fa(pos) = root;
Update(root);
}
else
{
Splay(Find(x+1),R(root));
L(R(root)) = pos ,Fa(pos) = R(root);
Update(Fa(pos)), Update(root);
}
}
size ++;
}
void Del(int x)
{
int pos = Find(x);
Splay(pos,root);
if(size == 1) root = 0;
else
{
int y;
if(x == size) y = L(root);
else
{
Splay(Find(x+1),R(root));
y = R(root);
L(y) = L(root) ,Fa(L(y)) = y;
}
Fa(y) = 0,root = y, Update(root);
}
Clear(pos);
size--;
}
void Add(int l,int r,int p)
{
int pos = GetInveral(l,r);
b[pos].val += p;
b[pos].min += p;
b[pos].add += p;
while(pos != root)
{
Update(Fa(pos));
pos = Fa(pos);
}
}
void Reverse(int l,int r)
{
int pos = GetInveral(l,r);
b[pos].rev ^= 1;
}
void Revolve(int l,int r,int T)
{
int len = r-l+1;
T = ((T%len)+len)%len;
if(!T) return;
Reverse(l,r-T);
Reverse(r-T+1,r);
Reverse(l,r);
}
int GetMin(int l,int r)
{
int pos = GetInveral(l,r);
return b[pos].min;
}
int BuildTree(int ll,int rr,int fa)
{
int ret = (ll + rr)>>1;
b[ret].fa = fa , b[ret].val = a[ret];
if(ll < ret) b[ret].c[0] = BuildTree(ll,ret-1,ret);
if(ret < rr) b[ret].c[1] = BuildTree(ret+1,rr,ret);
Update(ret);
return ret;
}
int read()
{
int x = 0, f = 1;char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f = -1; c = getchar();}
while(c >= '0' && c <= '9'){x = (x<<3) + (x<<1) + (c-'0'); c = getchar();}
return x * f;
}
void write(int x)
{
if(x < 0) putchar('-'),x = -x;
static char s[10];int sl = 0;
while(x) s[++sl] = x%10 + '0',x /= 10;
if(!sl) {putchar('0');return;}
while(sl) putchar(s[sl--]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("poj3580.in","r",stdin);
freopen("poj3580.out","w",stdout);
#endif
n = read();
for(int i = 1; i<= n; i++)
a[i] = read();
root = BuildTree(1,n,0);
blen = size = n;
m = read();
while(m--)
{
char s[10];int a, b, c;
scanf("%s",s);
switch(s[0])
{
case 'D':a = read();
Del(a);
break;
case 'I':a = read(), b = read();
Insert(a, b);
break;
case 'A':a = read(), b = read(), c = read();
Add(a, b, c);
break;
case 'M':a = read(), b = read();
write(GetMin(a, b));puts("");
break;
case 'R':
switch(s[3])
{
case 'E':a = read(), b = read();
Reverse(a, b);
break;
case 'O':a = read(), b = read(), c = read();
Revolve(a, b, c);
break;
}
break;
}
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}