题目大意:维护区间的最大值,要求可以区间翻转和区间加减。
思路:弱化版的1500,好长时间没写带标记的Splay了,错误重重。这个题可以当作带标记的Splay模板了。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define WORKPATH (root->son[1]->son[0])
using namespace std;
struct SplayTree{
int val,size;
int change,_max;
bool reverse;
SplayTree *son[2],*father;
SplayTree(int _);
bool Check() {
return father->son[1] == this;
}
void Combine(SplayTree *a,bool dir) {
son[dir] = a;
a->father = this;
}
void Plus(int c);
void Reverse();
void PushUp();
void PushDown();
}none(0),*nil = &none,*root;
SplayTree:: SplayTree(int _) {
val = _;
size = 1;
_max = change = 0;
reverse = false;
son[0] = son[1] = nil;
}
void SplayTree:: Plus(int c) {
if(this == nil) return ;
change += c;
val += c;
_max += c;
}
void SplayTree:: Reverse() {
if(this == nil) return ;
reverse ^= 1;
swap(son[0],son[1]);
}
void SplayTree:: PushUp() {
if(this == nil) return ;
size = son[0]->size + son[1]->size + 1;
_max = max(val,max(son[0]->_max,son[1]->_max));
}
void SplayTree:: PushDown() {
if(this == nil) return ;
if(change) {
son[0]->Plus(change);
son[1]->Plus(change);
change = 0;
}
if(reverse) {
son[0]->Reverse();
son[1]->Reverse();
reverse = false;
}
}
int cnt,asks;
SplayTree *BuildTree(int l,int r)
{
if(r < l) return nil;
int mid = (l + r) >> 1;
SplayTree *re = new SplayTree(0);
re->Combine(BuildTree(l,mid - 1),false);
re->Combine(BuildTree(mid + 1,r),true);
re->PushUp();
return re;
}
void Pretreatment()
{
nil->size = 0;
nil->father = nil;
nil->val = nil->_max = -INF;
root = BuildTree(0,cnt + 1);
root->father = nil;
}
inline void Rotate(SplayTree *a,bool dir)
{
SplayTree *f = a->father;
f->PushDown(),a->PushDown();
f->son[!dir] = a->son[dir];
f->son[!dir]->father = f;
a->son[dir] = f;
f->father->son[f->Check()] = a;
a->father = f->father;
f->father = a;
f->PushUp();
if(root == f) root = a;
}
inline void Splay(SplayTree *a,SplayTree *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);
}
}
a->PushUp();
}
SplayTree *Kth(SplayTree *a,int k)
{
a->PushDown();
if(k <= a->son[0]->size) return Kth(a->son[0],k);
k -= a->son[0]->size;
if(k == 1) return a;
return Kth(a->son[1],k - 1);
}
inline void SplaySeg(int x,int y)
{
x++,y++;
Splay(Kth(root,x - 1),nil);
Splay(Kth(root,y + 1),root);
}
int main()
{
cin >> cnt >> asks;
Pretreatment();
for(int flag,x,y,z,i = 1; i <= asks; ++i) {
scanf("%d",&flag);
if(flag == 1) {
scanf("%d%d%d",&x,&y,&z);
SplaySeg(x,y);
WORKPATH->Plus(z);
root->son[1]->PushUp();
root->PushUp();
}
else if(flag == 2) {
scanf("%d%d",&x,&y);
SplaySeg(x,y);
WORKPATH->Reverse();
}
else {
scanf("%d%d",&x,&y);
SplaySeg(x,y);
printf("%d\n",WORKPATH->_max);
}
}
return 0;
}