题目大意:维护一种数据结构,它支持以下功能:
1.ADD:从第x个点到第y个点每个点加z。
2.REVERSE:将序列的x到y翻转。
3.REVOLVE:处理序列x到y,把它的最后一个值放在第一个位置。重复这样的操作z次。
4.INSERT:在第x个数后面加入一个数p
5.DELETE:把序列第x个数删除。
6.MIN:求出序列x到y中的最小值。
思路:除了REVOLVE以外的操作都是SPLAY的常规操作,正常写就可以。REVOLVE也十分简单。只要算好两边端点的值,把它提到root->son[1]->son[0]上拿出来,再进行一些Splay操作,把刚才从树中取出的序列插入到树中就可以。
关于负数取模:REVOLVE中给出的值有可能是负的,只需要((a % MO) + MO) % MO就可以得到正确的正值
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define INF 0x3f3f3f3f
using namespace std;
struct Complex{
int val,size;
int _min;
Complex *father,*son[2];
int c;
bool reverse;
bool Check() {
return father->son[1] == this;
}
void Combine(Complex *a,bool dir) {
son[dir] = a;
a->father = this;
}
void Reverse() {
reverse ^= 1;
swap(son[0],son[1]);
}
void Plus(int num) {
val += num;
c += num;
_min += num;
}
}none,*nil = &none,*root;
int cnt;
int src[MAX];
char s[20];
void Pretreatment();
Complex *BuildTree(int l,int r);
inline Complex *NewComplex(int val);
Complex *Kth(Complex *a,int k);
inline void PushUp(Complex *a);
inline void PushDown(Complex *a);
inline void Rotate(Complex *a,bool dir);
inline void Splay(Complex *a,Complex *aim);
inline void SplaySeg(int l,int r);
int main()
{
Pretreatment();
cin >> cnt;
for(int i = 1;i <= cnt; ++i)
scanf("%d",&src[i]);
src[0] = src[cnt + 1] = INF;
root = BuildTree(0,cnt + 1);
root->father = nil;
cin >> cnt;
for(int x,y,z,i = 1;i <= cnt; ++i) {
scanf("%s",s);
if(!strcmp(s,"ADD")) {
scanf("%d%d%d",&x,&y,&z);
SplaySeg(x,y);
root->son[1]->son[0]->Plus(z);
PushUp(root->son[1]),PushUp(root);
}
if(!strcmp(s,"REVERSE")) {
scanf("%d%d",&x,&y);
SplaySeg(x,y);
root->son[1]->son[0]->Reverse();
}
if(!strcmp(s,"REVOLVE")) {
scanf("%d%d%d",&x,&y,&z);
int cnt = y - x + 1;
z = ((z % cnt) + cnt) % cnt;
SplaySeg(y - z + 1,y);
Complex *temp = root->son[1]->son[0];
root->son[1]->son[0]->father = nil;
root->son[1]->son[0] = nil;
PushUp(root->son[1]),PushUp(root);
Splay(Kth(root,x),nil);
Splay(Kth(root,x + 1),root);
root->son[1]->Combine(temp,false);
PushUp(root->son[1]),PushUp(root);
}
if(!strcmp(s,"INSERT")) {
scanf("%d%d",&x,&y);
Splay(Kth(root,x + 1),nil);
Splay(Kth(root,x + 2),root);
root->son[1]->Combine(NewComplex(y),false);
PushUp(root->son[1]),PushUp(root);
}
if(!strcmp(s,"DELETE")) {
scanf("%d",&x);
SplaySeg(x,x);
root->son[1]->son[0]->father = nil;
root->son[1]->son[0] = nil;
PushUp(root->son[1]),PushUp(root);
}
if(!strcmp(s,"MIN")) {
scanf("%d%d",&x,&y);
SplaySeg(x,y);
printf("%d\n",root->son[1]->son[0]->_min);
}
}
return 0;
}
void Pretreatment()
{
nil->son[0] = nil->son[1] = nil->father = nil;
nil->_min = INF;
}
Complex *BuildTree(int l,int r)
{
if(l > r) return nil;
int mid = (l + r) >> 1;
Complex *re = NewComplex(src[mid]);
re->Combine(BuildTree(l,mid - 1),false);
re->Combine(BuildTree(mid + 1,r),true);
PushUp(re);
return re;
}
inline Complex *NewComplex(int val)
{
Complex *re = new Complex();
re->son[0] = re->son[1] = nil;
re->reverse = false;
re->c = 0;
re->size = 1;
re->_min = re->val = val;
return re;
}
inline void PushUp(Complex *a)
{
if(a == nil) return ;
a->size = a->son[0]->size + a->son[1]->size + 1;
a->_min = min(a->val,min(a->son[0]->_min,a->son[1]->_min));
}
inline void PushDown(Complex *a)
{
if(a == nil) return ;
if(a->reverse) {
if(a->son[0] != nil) a->son[0]->Reverse();
if(a->son[1] != nil) a->son[1]->Reverse();
a->reverse = false;
}
if(a->c) {
if(a->son[0] != nil) a->son[0]->Plus(a->c);
if(a->son[1] != nil) a->son[1]->Plus(a->c);
a->c = 0;
}
}
inline void Rotate(Complex *a,bool dir)
{
Complex *f = a->father;
PushDown(f),PushDown(a);
f->son[!dir] = a->son[dir];
f->son[!dir]->father = f;
a->son[dir] = f;
a->father = f->father;
f->father->son[f->Check()] = a;
f->father = a;
PushUp(f);
if(root == f) root = a;
}
inline void Splay(Complex *a,Complex *aim)
{
while(a->father != aim) {
if(a->father->father == aim)
Rotate(a,!a->Check());
else if(!a->father->Check()) {
if(!a->Check())
Rotate(a->father,true),Rotate(a,true);
else Rotate(a,false),Rotate(a,true);
}
else {
if(a->Check())
Rotate(a->father,false),Rotate(a,false);
else Rotate(a,true),Rotate(a,false);
}
}
PushUp(a);
}
inline void SplaySeg(int l,int r)
{
l++,r++;
Splay(Kth(root,l - 1),nil);
Splay(Kth(root,r + 1),root);
}
Complex *Kth(Complex *a,int k)
{
PushDown(a);
if(a->son[0]->size >= k) return Kth(a->son[0],k);
k -= a->son[0]->size;
if(k == 1) return a;
return Kth(a->son[1],k - 1);
}