链接 : http://www.lydsy.com/JudgeOnline/problem.php?id=1500
如果都做到这题了,就不多说了
有很多的注意点,代码中有注释
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = ~0u>>2;
#define L ch[x][0]
#define R ch[x][1]
#define KT (ch[ ch[rt][1] ][0])
const int maxn = 500010;
struct SplayTree {
int sz[maxn];
int ch[maxn][2];
int pre[maxn];
int rt,top,top2;
int que[maxn],ss[maxn];
inline int max(int a,int b) {
return a>b?a:b;
}
inline void down(int x){
if(!x) return ;
if(flip[x]) {
flip[ L ] ^= 1;
flip[ R ] ^= 1;
swap(L,R);
swap(ls[x],rs[x]);
flip[x] = false ;
}
if(same[x]) {//注意防止将0节点赋值
if(L) same[ L ] = 1;
if(R) same[ R ] = 1;
if(L)val[ L ] = val[x];
if(R)val[ R ] = val[x];
if(L)sum[ L ] = val[x] * sz[ L ];
if(R)sum[ R ] = val[x] * sz[ R ];
if(L)mx_sum[L] = ls [ L ] = rs[ L ] = max(val[x],sum[ L ]);
if(R)mx_sum[R] = ls [ R ] = rs[ R ] = max(val[x],sum[ R ]);
same[x] = false ;
}
}
inline void up(int x){
if(!x) return;
if(L) down(L);
if(R) down(R);//关键所在,儿子节点的信息必须先down下去,不然有可能得到的mx_sum不是真实的
sz[x] = 1 + sz[ L ] + sz[ R ];
sum[x] = val[x] + sum[L] + sum[R];
ls[x] = max( ls[L] , sum[L] + val[x] + max(ls[R],0));
rs[x] = max( rs[R] , sum[R] + val[x] + max(rs[L],0));
mx_sum[x] = max(rs[L],0) + val[x] + max(ls[R],0);
mx_sum[x] = max(mx_sum[x],max(mx_sum[L],mx_sum[R]));
}
inline void Rotate(int x,int f){
int y=pre[x];
down(y);
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;
up(y);
}
inline void Splay(int x,int goal){//将x旋转到goal的下面
down(x);//防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了
while(pre[x] != goal){
down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变
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);
}
}
up(x);
if(goal==0) rt=x;
}
inline void RTO(int k,int goal){//将第k位数旋转到goal的下面
int x=rt;
down(x);
while(sz[ L ]+1 != k) {
if(k < sz[ L ] + 1 ) x=L;
else {
k-=(sz[ L ]+1);
x = R;
}
down(x);
}
Splay(x,goal);
}
inline void Newnode(int &x,int c,int f){
if(top2) x = ss[--top2];
else x = ++top;
L = R = 0; pre[x]=f;
sz[x] = 1;
val[x] = c; sum[x] = c;
flip[x] = same[x] = false;
ls[x] = rs[x] = mx_sum[x] = c;
}
inline void build(int &x,int l,int r,int f){
if(l>r) return ;
int m=l+r>>1;
Newnode(x,num[m],f);
build(L , l , m-1 , x);
build(R , m+1 , r , x);
pre[x]=f;
up(x);
}
inline void debug(){
vist(rt);
puts("");
}
inline void init(int n){
ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
rt=top=top2=0;
flip[0]=false; val[0]=0; sum[0]=0; same[0] = false;
ls[0] = rs[0] = mx_sum[0] = -inf;
for(int i = 1 ; i <= n ; i++) scanf("%d" , &num[i]);
Newnode(rt,-inf,0);
Newnode(ch[rt][1],-inf,rt);
sz[rt]=2;
build(KT,1,n,ch[rt][1]);
up(ch[rt][1]);
up(rt);
}
inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存
int father = pre[x];
int head = 0 , tail = 0;
for (que[tail++] = x ; head < tail ; head ++) {
ss[top2 ++] = que[head];
if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];
if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];
}
ch[ father ][ ch[father][1] == x ] = 0;
up(father);
}
void vist(int x){
if(x){
printf("结点%2d : 左儿子 %2d 右儿子 %2d val : %5d mxsum : %5d flip : %5d same : %d\n",x,
L,R,val[x],mx_sum[x],flip[x],same[x]);
vist(L);
vist(R);
}
}
inline void GET_SUM() {
scanf("%d%d",&pos,&tot);
int l=pos,r=pos+tot-1;
RTO(l,0);
RTO(r+2,rt);
printf("%d\n",sum[KT]);
}
inline void DELETE() {
scanf("%d%d",&pos,&tot);
int l=pos,r=tot+pos-1;
RTO(l,0);
RTO(r+2,rt);
erase(KT);
KT=0;
up(ch[rt][1]);
up(rt);
}
inline void INSERT() {
scanf("%d%d",&pos,&tot);
for(int i=1;i<=tot;i++) scanf("%d",&num[i]);
RTO(pos+1,0);
RTO(pos+2,rt);
build(KT,1,tot,ch[rt][1]);
up(ch[rt][1]); up(rt);
}
inline void MAKE_SAME() {
int c;
scanf("%d%d%d",&pos,&tot,&c);
int l=pos,r=pos+tot-1;
RTO(l,0);
RTO(r+2,rt);
same[KT] = true;
val[KT] = c;
sum[KT] = sz[KT] * c;
mx_sum[KT] = max( c , sum[KT] );
ls[KT] = max(c , sum[KT]);
rs[KT] = max(c , sum[KT]);
up(ch[rt][1]);
up(rt);
}
void print(int x) {
if(x) {
down(x);
print(L);
if(val[x]>-10000) {
if(flag) printf(" ");
printf("%d",val[x]);
flag=1;
}
print(R);
}
}
inline void OUT() {
flag=0;
print(rt);
printf("\n");
}
inline void REVERSE() {
scanf("%d%d",&pos,&tot);
int l=pos,r=pos+tot-1;
RTO(l,0);
RTO(r+2,rt);
flip[KT]^=1;
}
inline void MAX_SUM() {
RTO(1,0) ;
RTO(sz[rt],rt);
printf("%d\n",mx_sum[KT]);
}
int flag;
int pos,tot;
bool flip[maxn];
int val[maxn];
int num[maxn];
int sum[maxn];//求和
bool same[maxn];//统一修改为一个数
int ls[maxn];//最大前缀和
int rs[maxn];//最大后缀和
int mx_sum[maxn];//最大子列和
}spt;
int main()
{
int n,m,pos,tot;
scanf("%d%d",&n,&m);
spt.init(n);
char op[50];
while(m--) {
scanf("%s",op);
if(strcmp(op,"GET-SUM") == 0) {
spt.GET_SUM();
} else if(strcmp(op,"MAX-SUM") == 0) {
spt.MAX_SUM();
} else if(strcmp(op,"INSERT") == 0) {
spt.INSERT();
} else if(strcmp(op,"DELETE") == 0) {
spt.DELETE();
} else if(strcmp(op,"MAKE-SAME") == 0) {
spt.MAKE_SAME();
} else if(strcmp(op,"OUT") == 0) {
spt.OUT();
} else if(strcmp(op,"DEBUG") == 0){
spt.debug();
} else if(strcmp(op,"NEWTREE")==0){
spt.debug();
} else {
spt.REVERSE();
}
}
return 0;
}