P2042
题意给你6个操作 插入 删除 修改 翻转 求和 求和最大序列
因为涉及区间 所以我们预先放进去 1 这个点 和 arr[n+2] 这个点 相当于把数列右移了 1 单位
这样 l - 1 和 r + 1 就不用担心了 否则需要分类讨论
我们首先看插入 Insert 就是Build 一个新函数 然后插入到 x + 1 位置
删除是同理的
down和up要用线段树类似的维护 区别是线段树不需要管那个中间节点 splay需要
修改就是区间赋值
翻转区间反转
求和就是直接sum
最大子序列用线段树的方法维护即可
代码有点恶心 调了蛮久
因为可能会爆空间 所以用一个queue回收节点
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
const int MAX_N = 1000025;
int arr[MAX_N],ch[MAX_N][2],fa[MAX_N],sz[MAX_N],val[MAX_N],rev[MAX_N],setv[MAX_N],la[MAX_N],ra[MAX_N],ms[MAX_N],sum[MAX_N],root,ncnt,n,m;
queue<int> q;
void recycle(int x)
{
if(ch[x][0]) recycle(ch[x][0]);
if(ch[x][1]) recycle(ch[x][1]);
q.push(x);
}
int Newnode(int x)
{
int cur;
if(q.empty()) cur = ++ncnt;
else cur = q.front(),q.pop();
ch[cur][0] = ch[cur][1] = fa[cur] = 0;
val[cur] = sum[cur] = ms[cur] = x;
la[cur] = ra[cur] = max(0,x);
rev[cur] = setv[cur] = 0;
sz[cur] = 1;
return cur;
}
int chk(int x)
{
return ch[fa[x]][1] == x;
}
void pushup(int x)
{
int l = ch[x][0],r = ch[x][1];
sz[x] = sz[l] + sz[r] + 1;
sum[x] = sum[l] + sum[r] + val[x];
la[x] = max(la[l],sum[l]+val[x]+la[r]);
ra[x] = max(ra[r],sum[r]+val[x]+ra[l]);
ms[x] = max(ra[l] + val[x] + la[r],max(ms[l],ms[r]));
}
void Rotate(int x)
{
int y = fa[x],z = fa[y],k = chk(x), w = ch[x][k^1];
ch[y][k] = w;fa[w] = y;
ch[z][chk(y)] = x;fa[x] = z;
ch[x][k^1] = y;fa[y] = x;
pushup(y);pushup(x);
}
void Splay(int x,int goal = 0)
{
while(fa[x]!=goal)
{
int y = fa[x],z = fa[y];
if(z!=goal)
{
if(chk(x)==chk(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) root = x;
}
//辅助操作,将最大的小于等于 x 的数所在的节点splay到根。
void Find(int x)
{
if(!root) return;
int cur = root;
while(ch[cur][x>val[cur]]&&x!=val[cur])
{
cur = ch[cur][x>val[cur]];
}
Splay(cur);
}
void pushdown(int x)
{
int l = ch[x][0] , r = ch[x][1];
if(setv[x])
{
setv[x] = rev[x] = 0;
if(l)
{
setv[l] = 1;val[l] = val[x];
sum[l] = val[l] * sz[l];
la[l] = ra[l] = max(sum[l],0);
ms[l] = val[x]<0?val[x]:sum[l];
}
if(r)
{
setv[r] = 1;val[r] = val[x];
sum[r] = val[r] * sz[r];
la[r] = ra[r] = max(sum[r],0);
ms[r] = val[x]<0?val[x]:sum[r];
}
}
if(rev[x])
{
rev[l] ^= 1;rev[r] ^= 1;rev[x] = 0;
swap(la[l],ra[l]);swap(la[r],ra[r]);
swap(ch[l][0],ch[l][1]);
swap(ch[r][0],ch[r][1]);
}
}
int build(int l,int r,int *arr)
{
if(l>r) return 0;
int mid = (l+r)>>1,cur = Newnode(arr[mid]);
if(l==r) return cur;
if((ch[cur][0] = build(l,mid-1,arr))) fa[ch[cur][0]] = cur;
if((ch[cur][1] = build(mid+1,r,arr))) fa[ch[cur][1]] = cur;
pushup(cur);
return cur;
}
int Kth(int k)
{
int cur = root;
while(1)
{
pushdown(cur);
if(ch[cur][0]&&k<=sz[ch[cur][0]])
{
cur = ch[cur][0];
}
else if(k>sz[ch[cur][0]]+1)
{
k -= sz[ch[cur][0]] + 1;
cur = ch[cur][1];
}
else return cur;
}
}
void Insert(int x,int y)
{
int u = Kth(x+1), v = Kth(x+2);
Splay(u);Splay(v,u);
ch[v][0] = y;fa[y] = v;
pushup(v);pushup(u);
}
void Reverse(int x,int y)
{
int u = Kth(x), v = Kth(x+y+1);
Splay(u);Splay(v,u);
int w = ch[v][0];
if(!setv[w])
{
rev[w]^=1;
swap(ch[w][0],ch[w][1]);
swap(la[w],ra[w]);
pushup(v);pushup(u);
}
}
void update(int x,int y,int z)
{
int u = Kth(x),v = Kth(x+y+1);
Splay(u);Splay(v,u);
int w = ch[v][0];
setv[w] = 1;val[w] = z;sum[w] = sz[w]*z;
la[w] = ra[w] = max(0,sum[w]);
ms[w] = z<0?z:sum[w];
pushup(v);pushup(u);
}
void Remove(int x,int y)
{
int u = Kth(x),v = Kth(x+y+1);
Splay(u);Splay(v,u);
recycle(ch[v][0]);
ch[v][0] = 0;
pushup(v);pushup(u);
}
int qsum(int x,int y)
{
int u = Kth(x),v=Kth(x+y+1);
Splay(u);Splay(v,u);
return sum[ch[v][0]];
}
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int x,y,z;
scanf("%d%d",&n,&m);
char str[15];
for(int i = 2;i<=n+1;++i)
scanf("%d",arr+i);
ms[0] = val[0] = _inf;
arr[1] = arr[n+=2] = _inf;
build(1,n,arr);root=1;
while(m--)
{
scanf("%s",str);
if(str[0]=='I')
{
scanf("%d%d",&x,&y);
memset(arr,0,sizeof(arr));
for(int i = 1;i<=y;++i)
scanf("%d",arr+i);
Insert(x,build(1,y,arr));
}
else if(str[0]=='D')
{
scanf("%d%d",&x,&y);
Remove(x,y);
}
else if(str[0]=='M')
{
if(str[2]=='K')
{
scanf("%d%d%d",&x,&y,&z);
update(x,y,z);
}
else
{
printf("%d\n",ms[root]);
}
}
else if(str[0]=='R')
{
scanf("%d%d",&x,&y);
Reverse(x,y);
}
else if(str[0]=='G')
{
scanf("%d%d",&x,&y);
printf("%d\n",qsum(x,y));
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}