这是一道大数据结构题,7月初调了一整天没调出来。昨天突然心血来潮花了一个中午和一个晚自习终于AC了这道大模板题。
其实这道大模拟没有太多思路可言,一定要注意在回收内存时是否将节点信息重置。
即不仅要清空
f
i
f_{i}
fi , 还要顺便清空该节点所维护的所有信息,如:
s
u
m
v
sumv
sumv ,
m
a
x
v
maxv
maxv 等
Code:
#include<stack>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 500000 + 200;
const int inf = -1223;
int ch[maxn][2], f[maxn], numv[maxn], maxv[maxn], lmax[maxn], rmax[maxn], sumv[maxn], tag[maxn], lazy[maxn],siz[maxn];
int root, arr[maxn];
stack <int> S;
struct Operation
{
inline void init(){ for(int i = maxn - 10; i >= 1; --i) S.push(i); }
inline int new_node(){ int u = S.top(); S.pop(); return u; }
inline void erase(int x)
{
ch[x][0] = ch[x][1] = f[x] = 0;
maxv[x] = numv[x] = lmax[x] = rmax[x] = sumv[x] = tag[x] = siz[x] = 0;
lazy[x] = inf;
}
inline void trash(int u)
{
if(!u) return ;
S.push(u);
trash(ch[u][0]);
trash(ch[u][1]);
erase(u);
}
inline void pushup(int o)
{
int ls = ch[o][0], rs = ch[o][1];
maxv[o] = numv[o];
sumv[o] = sumv[ls] + sumv[rs] + numv[o];
siz[o] = siz[ls] + siz[rs] + 1;
int sums = numv[o];
if(ls) maxv[o] = max(maxv[o], maxv[ls]), sums += rmax[ls];
if(rs) maxv[o] = max(maxv[o], maxv[rs]), sums += lmax[rs];
maxv[o] = max(maxv[o], sums);
lmax[o] = max(lmax[ls], sumv[ls] + numv[o] + lmax[rs]);
rmax[o] = max(rmax[rs], sumv[rs] + numv[o] + rmax[ls]);
}
inline void maintain(int o)
{
maxv[o] = max(numv[o], sumv[o]);
lmax[o] = rmax[o] = max(0, sumv[o]);
}
inline void pushdown(int x)
{
int ls = ch[x][0], rs = ch[x][1];
if(lazy[x] != inf)
{
if(ls){ numv[ls] = lazy[ls] = lazy[x], sumv[ls] = siz[ls] * numv[ls]; maintain(ls); }
if(rs){ numv[rs] = lazy[rs] = lazy[x], sumv[rs] = siz[rs] * numv[rs]; maintain(rs); }
lazy[x] = inf;
}
if(tag[x])
{
swap(lmax[ls], rmax[ls]); swap(lmax[rs], rmax[rs]);
swap(ch[ls][0], ch[ls][1]); swap(ch[rs][0], ch[rs][1]);
if(ls) tag[ls] ^= 1;
if(rs) tag[rs] ^= 1;
tag[x] = 0;
}
}
void build(int l,int r,int fa,int &o)
{
if(l > r) return ;
int mid = (l + r) >> 1;
o = new_node();
f[o] = fa, numv[o] = arr[mid], lazy[o] = inf;
build(l, mid - 1, o, ch[o][0]);
build(mid + 1, r, o, ch[o][1]);
pushup(o);
}
}T;
inline int get(int x){ return ch[f[x]][1] == x;}
inline void rotate(int x)
{
int old = f[x], oldf = f[old], which = get(x);
ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old;
ch[x][which ^ 1] = old, f[old] = x, f[x] = oldf;
if(oldf)
ch[oldf][ch[oldf][1] == old] = x;
T.pushup(old); T.pushup(x);
}
inline void splay(int x,int &tar)
{
int a = f[tar];
for(int fa; (fa = f[x]) != a; rotate(x))
if(f[fa] != a) rotate(get(x) == get(fa) ? fa : x);
tar = x;
}
inline int findx(int x, int top)
{
int cur = top;
while(1)
{
T.pushdown(cur);
int ls = ch[cur][0];
if(x == siz[ls] + 1) return cur;
if(x <= siz[ls]) cur = ch[cur][0];
else x -= siz[ls] + 1, cur = ch[cur][1];
}
return 0;
}
inline void split(int &a, int nums, int &b)
{
if(nums == 0)
{
b = a, a = 0; return ;
}
if(nums == siz[a])
{
b = 0; return ;
}
int u = findx(nums, a);
splay(u, a);
b = ch[a][1], f[ch[a][1]] = 0 , ch[a][1] = 0;
T.pushup(a);
}
inline void merge(int &a, int &b)
{
if(!a)
{
a = b; return ;
}
int u = findx(siz[a], a);
splay(u, a);
ch[a][1] = b, f[ch[a][1]] = a;
T.pushup(a);
}
inline void Insert()
{
int pos, tot;
scanf("%d%d",&pos,&tot);
for(int i = 1;i <= tot; ++i) scanf("%d",&arr[i]);
int a = 0, b = 0;
split(root, pos, a);
T.build(1, tot, 0, b);
merge(root, b);
merge(root, a);
}
inline void Delete()
{
int pos, tot;
scanf("%d%d",&pos,&tot);
int a , b;
split(root, pos - 1, a);
split(a, tot, b);
T.trash(a);
merge(root, b);
}
inline void Make_Same()
{
int pos, tot, c, a = 0, b = 0;
scanf("%d%d%d",&pos,&tot,&c);
split(root, pos - 1, a), split(a, tot, b);
sumv[a] = siz[a] * c, lazy[a] = c, numv[a] = c;
T.maintain(a);
merge(root, a), merge(root, b);
}
inline void Reverse()
{
int pos, tot, a = 0, b = 0;
scanf("%d%d",&pos,&tot);
split(root, pos - 1, a); split(a, tot, b);
tag[a] ^= 1;
swap(lmax[a], rmax[a]), swap(ch[a][0], ch[a][1]);
merge(root, a), merge(root, b);
}
inline void Get_sum()
{
int pos, tot, a = 0, b = 0;
scanf("%d%d",&pos,&tot);
split(root, pos - 1, a), split(a, tot, b);
printf("%d\n",sumv[a]);
merge(root, a), merge(root, b);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
T.init();
for(int i = 1;i <= n; ++i) scanf("%d",&arr[i]);
T.build(1, n, 0, root);
for(int i = 1;i <= m; ++i)
{
char str[30];
scanf("%s",str);
if(str[0] == 'I') Insert();
if(str[0] == 'D') Delete();
if(str[2] == 'K') Make_Same();
if(str[0] == 'R') Reverse();
if(str[0] == 'G') Get_sum();
if(str[2] == 'X') printf("%d\n",maxv[root]);
}
return 0;
}