做过维护数列那道题后这道题做起来好多了。
主要说一下REVOLVE操作,要求把[l,r]这个区间的数向后循环t次,其实这个操作相当交换[l,r - t]与[r - x + 1,r]这两个区间,不过操作的时候注意要把t先对区间长度取模。
其他的操作就比较简单,类似维护数列。
代码:
#include<cstdio>
#include<cstring>
#define keyTree ch[ch[root][1]][0]
using namespace std;
const int maxn = 300000;
const int inf = 0x3f3f3f3f;
struct SplayTree
{
int ch[maxn][2],pre[maxn];
int val[maxn],Min[maxn],sz[maxn];
int lazy[maxn],num[maxn];
bool reverse[maxn];
int root,top;
int min(int a,int b){return a < b ? a : b;}
void swap(int &a,int &b){int t = a;a = b;b = t;}
void push_up(int x)
{
Min[x] = min(val[x],min(Min[ ch[x][0] ],Min[ ch[x][1] ]));
sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;
}
void add(int x,int v)
{
val[x] += v;
lazy[x] += v;
Min[x] += v;
}
void push_down(int x)
{
if(lazy[x])
{
if(ch[x][0])add(ch[x][0],lazy[x]);
if(ch[x][1])add(ch[x][1],lazy[x]);
lazy[x] = 0;
}
if(reverse[x])
{
reverse[ ch[x][0] ] = !reverse[ ch[x][0] ];
reverse[ ch[x][1] ] = !reverse[ ch[x][1] ];
swap(ch[x][0],ch[x][1]);
reverse[x] = false;
}
}
void Rotate(int x,int f)
{
int y = pre[x];
push_down(y);push_down(x);
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x])ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
ch[x][f] = y;
pre[y] = x;
push_up(y);
}
void Splay(int x,int goal)
{
push_down(x);
while(pre[x] != goal)
{
if(pre[pre[x]] == goal)Rotate(x,ch[pre[x]][0] == x);
else
{
int y = pre[x],z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x)Rotate(x,!f),Rotate(x,f);
else Rotate(y,f),Rotate(x,f);
}
}
push_up(x);
if(goal == 0)root = x;
}
void RotateTo(int k,int goal)
{
int x = root;
push_down(x);
while(sz[ ch[x][0] ] != k)
{
if(k < sz[ ch[x][0] ])x = ch[x][0];
else
{
k -= (sz[ ch[x][0] ] + 1);
x = ch[x][1];
}
push_down(x);
}
Splay(x,goal);
}
void Newnode(int &x,int key)
{
x = ++top;
ch[x][0] = ch[x][1] = pre[x] = 0;
sz[x] = 1;
lazy[x] = 0;
reverse[x] = false;
val[x] = Min[x] = key;
}
void makeTree(int &x,int l,int r,int f,int *p)
{
if(l > r)return;
int m = (l + r) >> 1;
Newnode(x,p[m]);
makeTree(ch[x][0],l,m - 1,x,p);
makeTree(ch[x][1],m + 1,r,x,p);
pre[x] = f;
push_up(x);
}
void init(int n)
{
ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
root = top = 0;
reverse[0] = val[0] = lazy[0] = 0;Min[0] = inf;
Newnode(root,inf);
Newnode(ch[root][1],inf);
pre[ch[root][1]] = root;
sz[root] = 2;
for(int i = 1;i <= n;i++)scanf("%d",&num[i]);
makeTree(keyTree,1,n,ch[root][1],num);
push_up(ch[root][1]);
push_up(root);
}
void insert(int x,int pos)
{
RotateTo(pos,0);RotateTo(pos + 1,root);
Newnode(keyTree,x);
pre[keyTree] = ch[root][1];
push_up(ch[root][1]);push_up(root);
}
void update(int l,int r,int c)
{
RotateTo(l - 1,0);RotateTo(r + 1,root);
add(keyTree,c);
push_up(ch[root][1]);push_up(root);
}
void rev(int l,int r)
{
RotateTo(l - 1,0);RotateTo(r + 1,root);
reverse[ keyTree ] = !reverse[ keyTree ];
}
void work(int l,int r,int num)
{
num = (num % (r - l + 1) + (r - l + 1)) % (r - l + 1);
if(!num)return;
RotateTo(r - num,0);RotateTo(r + 1,root);
int tmp = keyTree;
keyTree = 0;
push_up(ch[root][1]);push_up(root);
RotateTo(l - 1,0);RotateTo(l,root);
keyTree = tmp;
pre[ keyTree ] = ch[root][1];
push_up(ch[root][1]);push_up(root);
}
int query(int l,int r)
{
RotateTo(l - 1,0);RotateTo(r + 1,root);
return Min[ keyTree ];
}
void erace(int pos)
{
RotateTo(pos - 1,0);RotateTo(pos + 1,root);
keyTree = 0;
push_up(ch[root][1]);push_up(root);
}
}Spt;
int n,m;
void init()
{
freopen("poj3580.in","r",stdin);
freopen("poj3580.out","w",stdout);
}
void readdata()
{
scanf("%d",&n);
Spt.init(n);
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
char op[10];
scanf("%s",op);
if(!strcmp(op,"ADD"))
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
Spt.update(l,r,c);
}
if(!strcmp(op,"REVERSE"))
{
int l,r;
scanf("%d%d",&l,&r);
Spt.rev(l,r);
}
if(!strcmp(op,"REVOLVE"))
{
int l,r,t;
scanf("%d%d%d",&l,&r,&t);
Spt.work(l,r,t);
}
if(!strcmp(op,"INSERT"))
{
int pos,x;
scanf("%d%d",&pos,&x);
Spt.insert(x,pos);
}
if(!strcmp(op,"MIN"))
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",Spt.query(l,r));
}
if(!strcmp(op,"DELETE"))
{
int pos;
scanf("%d",&pos);
Spt.erace(pos);
}
}
}
int main()
{
init();
readdata();
return 0;
}