题目描述

输入
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
输出
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
样例输入
9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
样例输出
-1
10
1
10
题解
做了4小时的Splay“裸题”。
大概就是各种细节处理一下就行了。
这里ls和rs的数的个数可以为0,但ts的数的个数一定大于0,应该可以在代码中pushup部分理解。
ts[0]要赋成极小值,否则pushup时可能会因使用到0节点而不为真正值。
当某数为负数时,ls和rs为0,但是ts为v,即小于0。这点在pushdown中尤其突出。
pushdown中有无儿子的问题,一定要判断。
不能开特大空间,所以需要循环利用下标,把能用的下标存到一个队列中,加入时取出队首,删除时加到队尾。
搞定细节以后(话说不是先敲大体在搞细节吗),就是splay裸题。
220行丑丑的代码。。
#include <cstdio>
#include <cstring>
#include <queue>
#define N 600010
using namespace std;
int sum[N] , v[N] , ls[N] , rs[N] , ts[N] , si[N] , rev[N] , tag[N] , c[2][N] , fa[N] , root;
char str[20];
queue<int> q;
inline int read()
{
int num = 0 , f = 1; char ch = getchar();
while(ch < ‘0‘ || ch > ‘9‘){if(ch == ‘-‘)f = -1; ch = getchar();}
while(ch >= ‘0‘ && ch <= ‘9‘) num = (num << 3) + (num << 1) + ch - ‘0‘ , ch = getchar();
return num * f;
}
void pushup(int k)
{
int l = c[0][k] , r = c[1][k];
sum[k] = sum[l] + sum[r] + v[k];
ls[k] = max(ls[l] , sum[l] + v[k] + ls[r]);
rs[k] = max(rs[r] , sum[r] + v[k] + rs[l]);
ts[k] = max(max(ts[l] , ts[r]) , rs[l] + v[k] + ls[r]);
si[k] = si[l] + si[r] + 1;
}
void pushdown(int k)
{
int l = c[0][k] , r = c[1][k];
if(tag[k] != 0x3f3f3f3f)
{
if(l) sum[l] = si[l] * tag[k] , v[l] = tag[l] = tag[k];
if(r) sum[r] = si[r] * tag[k] , v[r] = tag[r] = tag[k];
if(tag[k] > 0)
{
if(l) ls[l] = rs[l] = ts[l] = si[l] * tag[k];
if(r) ls[r] = rs[r] = ts[r] = si[r] * tag[k];
}
else
{
if(l) ls[l] = rs[l] = 0 , ts[l] = tag[k];
if(r) ls[r] = rs[r] = 0 , ts[r] = tag[k];
}
tag[k] = 0x3f3f3f3f;
}
if(rev[k])
{
swap(c[0][l] , c[1][l]);
swap(c[0][r] , c[1][r]);
swap(ls[l] , rs[l]);
swap(ls[r] , rs[r]);
rev[l] ^= 1;
rev[r] ^= 1;
rev[k] = 0;
}
}
void build(int l , int r , int f)
{
if(l > r) return;
int mid = (l + r) >> 1;
build(l , mid - 1 , mid);
build(mid + 1 , r , mid);
fa[mid] = f;
c[mid > f][f] = mid;
pushup(mid);
}
void rotate(int &k , int x)
{
int y = fa[x] , z = fa[y] , l , r;
l = (c[0][y] != x);
r = l ^ 1;
if(y == k) k = x;
else if(c[0][z] == y) c[0][z] = x;
else c[1][z] = x;
fa[x] = z;
fa[y] = x;
fa[c[r][x]] = y;
c[l][y] = c[r][x];
c[r][x] = y;
pushup(y);
pushup(x);
}
void splay(int &k , int x)
{
while(k != x)
{
int y = fa[x] , z = fa[y];
if(y != k)
{
if(c[0][z] == y ^ c[0][y] == x) rotate(k , x);
else rotate(k , y);
}
rotate(k , x);
}
}
int find(int k , int x)
{
pushdown(k);
if(x <= si[c[0][k]]) return find(c[0][k] , x);
else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
else return k;
}
void update(int l , int r , int x)
{
int ta , tb , t;
ta = find(root , l - 1);
splay(root , ta);
tb = find(root , r + 1);
splay(c[1][root] , tb);
t = c[0][c[1][root]];
sum[t] = si[t] * x;
if(x > 0) ls[t] = rs[t] = ts[t] = si[t] * x;
else ls[t] = rs[t] = 0 , ts[t] = x;
v[t] = tag[t] = x;
pushup(c[1][root]);
pushup(root);
}
void rever(int l , int r)
{
int ta , tb , t;
ta = find(root , l - 1);
splay(root , ta);
tb = find(root , r + 1);
splay(c[1][root] , tb);
t = c[0][c[1][root]];
swap(c[0][t] , c[1][t]);
swap(ls[t] , rs[t]);
rev[t] ^= 1;
}
void cls(int k)
{
if(k)
{
int l = c[0][k] , r = c[1][k];
cls(l) , q.push(k) , cls(r);
tag[k] = 0x3f3f3f3f;
rev[k] = sum[k] = si[k] = ls[k] = rs[k] = ts[k] = c[0][k] = c[1][k] = fa[k] = 0;
}
}
int main()
{
int n , m , i , p , t , x , ta , tb , id;
n = read() , m = read();
for(i = 2 ; i <= n + 1 ; i ++ )
v[i] = read();
memset(tag , 0x3f , sizeof(tag));
ts[0] = 0xc0000000;
build(1 , n + 2 , 0);
root = (n + 3) >> 1;
for(i = n + 3 ; i <= 600005 ; i ++ ) q.push(i);
while(m -- )
{
scanf("%s" , str);
switch(str[2])
{
case ‘S‘:
{
p = read() , t = read();
for(i = 1 ; i <= t ; i ++ )
{
ta = find(root , p + i);
splay(root , ta);
tb = find(root , p + i + 1);
splay(c[1][root] , tb);
x = read();
id = q.front() , q.pop();
v[id] = x;
fa[id] = c[1][root];
c[0][c[1][root]] = id;
pushup(c[0][c[1][root]]);
pushup(c[1][root]);
pushup(root);
}
break;
}
case ‘L‘:
{
p = read() , t = read();
ta = find(root , p);
splay(root , ta);
tb = find(root , p + t + 1);
splay(c[1][root] , tb);
cls(c[0][c[1][root]]);
c[0][c[1][root]] = 0;
pushup(c[1][root]);
pushup(root);
break;
}
case ‘K‘:
{
p = read() , t = read() , x = read();
update(p + 1 , p + t , x);
break;
}
case ‘V‘:
{
p = read() , t = read();
rever(p + 1 , p + t);
break;
}
case ‘T‘:
{
p = read() , t = read();
ta = find(root , p);
splay(root , ta);
tb = find(root , p + t + 1);
splay(c[1][root] , tb);
printf("%d\n" , sum[c[0][c[1][root]]]);
break;
}
default:
{
ta = find(root , 1);
splay(root , ta);
tb = find(root , si[root]);
splay(c[1][root] , tb);
printf("%d\n" , ts[c[0][c[1][root]]]);
}
}
}
return 0;
}
原文:http://www.cnblogs.com/GXZlegend/p/6440155.html