Description
请写一个程序,要求维护一个数列,支持以下 6 种操作:
请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
Sample Output
-1
10
1
10
HINT
听说是splay模板题,怎么这么不友好QAQ
注意区间修改时标记要提前下传,翻转时也要提前下传!并更新相关的信息
细节比较多,上面这个细节比较关键
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define ll long long
#define ls tr[x].ch[0]
#define rs tr[x].ch[1]
using namespace std;
const int INF = 1000000000;
int root , tot ;
int a[1001000];
struct Splay{
int ch[2],val,sz,cnt,fa;
int lmx,rmx,mx,sum,det;
bool rev;
}tr[1001000];
void read(int &sum){sum = 0;char c = getchar();bool flag = true;while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();if(!flag) sum = -sum;}
queue<int>has;
void update(int x)
{
if(!x) return;
tr[x].sz = tr[ls].sz + tr[rs].sz + tr[x].cnt;
tr[x].lmx = max(tr[ls].lmx,tr[ls].sum + tr[x].val + max(0,tr[rs].lmx));
tr[x].rmx = max(tr[rs].rmx,tr[rs].sum + tr[x].val + max(0,tr[ls].rmx));
tr[x].mx = max( max(tr[ls].mx,tr[rs].mx) , max(tr[ls].rmx , 0) + tr[x].val + max(tr[rs].lmx , 0) );
tr[x].sum = tr[ls].sum + tr[rs].sum + tr[x].val;
}
void zig(int x)
{
int y = tr[x].fa;int z = tr[y].fa;
int k = tr[y].ch[1] == x;
tr[z].ch[tr[z].ch[1] == y] = x; tr[x].fa = z;
tr[y].ch[k] = tr[x].ch[k^1]; tr[tr[x].ch[k^1]].fa = y;
tr[x].ch[k^1] = y; tr[y].fa = x;
update(y);update(x);
}
int pick()
{
int t;
if(!has.empty()) t = has.front() , has.pop();
else t = ++tot;
return t;
}
void reverse(int x)
{
if(!x) return;
swap(ls,rs);
swap(tr[x].lmx,tr[x].rmx);
tr[x].rev ^= 1;
}
void recover(int x,int v)
{
if(!x) return;
tr[x].val = tr[x].det = v;
tr[x].sum = tr[x].sz *v;
tr[x].lmx = tr[x].rmx = tr[x].mx = max(v,tr[x].sum);
}
void pushdown(int x)
{
if(tr[x].rev)
{
reverse(ls);
reverse(rs);
tr[x].rev = 0;
}
if(tr[x].det != -INF)
{
recover(ls,tr[x].det);
recover(rs,tr[x].det);
tr[x].det = -INF;
}
}
void relax(int x,int R)
{
if(tr[x].fa != R) relax(tr[x].fa , R);
pushdown(x);
}
void splay(int x,int R)
{
relax(x,R);
while(tr[x].fa != R)
{
int y = tr[x].fa;int z = tr[y].fa;
if(z != R)
(tr[z].ch[1] == y)^(tr[y].ch[1] == x) ? zig(x):zig(y);
zig(x);
}
if(R == 0) root = x;
}
int setup(int x)
{
int t = pick();
tr[t].val = a[x];
tr[t].cnt = 1;
tr[t].rev = 0;
tr[t].lmx = tr[t].rmx = tr[t].mx = -INF;
tr[t].det = -INF;
return t;
}
int build(int l,int r)
{
int mid = (l + r)>>1 ,left = 0 , right = 0;
if(l < mid) left = build(l,mid-1);
int x = setup(mid);
if(r > mid) right = build(mid+1,r);
if(left) ls = left , tr[left].fa = x;
else ls = 0;
if(right) rs = right , tr[right].fa = x;
else rs = 0;
update(x);
return x;
}
int find(int rank)
{
int x = root;
while(1)
{
pushdown(x);
if(tr[ls].sz + tr[x].cnt < rank) rank -= tr[ls].sz + tr[x].cnt , x = rs;
else if(tr[ls].sz >= rank) x = ls;
else return x;
}
}
void recycle(int x)
{
has.push(x);
if(ls) recycle(ls);
if(rs) recycle(rs);
return;
}
int cas;
char q[15];
int main()
{
int n , m;
read(n);read(m);
tr[0].mx = tr[0].lmx = tr[0].rmx = -INF;
rep(i,2,n+1) read(a[i]);
a[1] = a[n+2] = 0;
root = build(1,n+2);
rep(i,1,m)
{
scanf("%s",q);
if(q[0] == 'I')
{
int rk , num;read(rk);read(num);
rep(i,1,num) read(a[i]);
int tmp = build(1,num);
int x = find(rk+1);splay(x,0);
int y = find(rk+2);splay(y,x);
tr[y].ch[0] = tmp;tr[tmp].fa = y;
update(y);update(x);
}
if(q[0] == 'D')
{
int rk , num;read(rk);read(num);
int x = find(rk);splay(x,0);;
int y = find(rk+num+1);splay(y,x);
recycle(tr[y].ch[0]);
tr[y].ch[0] = 0;
update(y);update(x);
}
if(q[0] == 'M' && q[2] == 'K')
{
int rk , num;read(rk);read(num);
int x = find(rk);splay(x,0);
int y = find(rk+num+1);splay(y,x);
int c ;read(c);
recover(tr[y].ch[0],c);
}
if(q[0] == 'R')
{
int rk , num;read(rk);read(num);
int x = find(rk);splay(x,0);
int y = find(rk+num+1);splay(y,x);
reverse(tr[y].ch[0]);
}
if(q[0] == 'G')
{
int rk , num;read(rk);read(num);cas++;
int x = find(rk);splay(x,0);
int y = find(rk+num+1);splay(y,x);
printf("%d\n",tr[tr[y].ch[0]].sum);
}
if(q[0] == 'M' && q[2] == 'X')
{
splay(1,0);splay(n+2,1);
printf("%d\n",tr[tr[n+2].ch[0]].mx);
}
}
return 0;
}