题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1251
题目大意:维护3种操作:区间加、区间翻转、询问区间Max。
算法讨论:
说是“终结者”,其实只是一题入门题和模板题而已。
区间翻转显然用的是Splay。
然后就OK了。
Code:
/*
* Problem:1251
* Author:PYC
*/
#include
#include
#include
#define maxn 1000000
#define oo 1000000000
using namespace std;
int n,m,tot,root;
struct node{
int key,Max,add,l,r,ll,rr,fa;
bool rev;
}tree[maxn];
void up(int rt){
tree[rt].Max=max(tree[rt].key,max(tree[rt].l?tree[tree[rt].l].Max:-oo,tree[rt].r?tree[tree[rt].r].Max:-oo));
}
void down(int rt){
if (tree[rt].add){
tree[tree[rt].l].add+=tree[rt].add;
tree[tree[rt].r].add+=tree[rt].add;
tree[tree[rt].l].key+=tree[rt].add;
tree[tree[rt].r].key+=tree[rt].add;
tree[tree[rt].l].Max+=tree[rt].add;
tree[tree[rt].r].Max+=tree[rt].add;
tree[rt].add=0;
}
if (tree[rt].rev){
tree[tree[rt].l].rev^=1;
tree[tree[rt].r].rev^=1;
swap(tree[tree[rt].l].l,tree[tree[rt].l].r);
swap(tree[tree[rt].r].l,tree[tree[rt].r].r);
swap(tree[tree[rt].l].ll,tree[tree[rt].l].rr);
swap(tree[tree[rt].r].ll,tree[tree[rt].r].rr);
tree[rt].rev=0;
}
}
void build(int &rt,int l,int r){
int mid=(l+r)/2;
rt=++tot;
if (l==r) return;
if (mid-l){
tree[rt].ll=mid-l;
build(tree[rt].l,l,mid-1);
tree[tree[rt].l].fa=rt;
}
if (r-mid){
tree[rt].rr=r-mid;
build(tree[rt].r,mid+1,r);
tree[tree[rt].r].fa=rt;
}
up(rt);
}
int kth(int rt,int y){
down(rt);
if (y==tree[rt].ll+1) return rt;
if (ytree[rt].ll+1) return kth(tree[rt].r,y-tree[rt].ll-1);
}
void zig(int rt){
int t=tree[rt].l;
tree[rt].l=tree[t].r;
tree[rt].ll=tree[t].rr;
tree[t].r=rt;
tree[t].rr+=tree[rt].rr+1;
tree[t].fa=tree[rt].fa;
tree[rt].fa=t;
tree[tree[rt].l].fa=rt;
if (rt==tree[tree[t].fa].l) tree[tree[t].fa].l=t;
else tree[tree[t].fa].r=t;
up(rt);
up(t);
}
void zag(int rt){
int t=tree[rt].r;
tree[rt].r=tree[t].l;
tree[rt].rr=tree[t].ll;
tree[t].l=rt;
tree[t].ll+=tree[rt].ll+1;
tree[t].fa=tree[rt].fa;
tree[rt].fa=t;
tree[tree[rt].r].fa=rt;
if (rt==tree[tree[t].fa].l) tree[tree[t].fa].l=t;
else tree[tree[t].fa].r=t;
up(rt);
up(t);
}
void splay(int x,int &rt){
stack Q;
for (int i=x;i;i=tree[i].fa) Q.push(i);
while (!Q.empty()){
down(Q.top());
Q.pop();
}
int fa=tree[rt].fa;
while (tree[x].fa!=fa){
int y=tree[x].fa,z=tree[y].fa;
if (z==fa){
if (x==tree[y].l) zig(y);
else zag(y);
}
else if (y==tree[z].l){
if (x==tree[y].l){zig(z);zig(y);}
else{zag(y);zig(z);}
}
else{
if (x==tree[y].r){zag(z);zag(y);}
else{zig(y);zag(z);}
}
}
rt=x;
}
int ask(int l,int r){
splay(kth(root,l),root);
splay(kth(root,r+2),tree[root].r);
up(root);
return tree[tree[tree[root].r].l].Max;
}
void add(int l,int r,int d){
splay(kth(root,l),root);
splay(kth(root,r+2),tree[root].r);
up(root);
tree[tree[tree[root].r].l].key+=d;
tree[tree[tree[root].r].l].Max+=d;
tree[tree[tree[root].r].l].add+=d;
}
void reverse(int l,int r){
splay(kth(root,l),root);
splay(kth(root,r+2),tree[root].r);
up(root);
tree[tree[tree[root].r].l].rev^=1;
swap(tree[tree[tree[root].r].l].l,tree[tree[tree[root].r].l].r);
swap(tree[tree[tree[root].r].l].ll,tree[tree[tree[root].r].l].rr);
}
int main(){
scanf("%d%d",&n,&m);
build(root,0,n+1);
for (int i=1;i<=m;++i){
int x;
scanf("%d",&x);
if (x==3){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",ask(l,r));
}
if (x==1){
int l,r,d;
scanf("%d%d%d",&l,&r,&d);
add(l,r,d);
}
if (x==2){
int l,r;
scanf("%d%d",&l,&r);
reverse(l,r);
}
}
return 0;
}
By Charlie Pan
Mar 4,2014