Description
Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。
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
Source
Splay
前五种是基本操作。
对于第六种,多保存几个值。当前区间包含左端点的答案lx,包含右端点的答案rx,整个区间的答案mx。这样就能向上更新。跟线段树的做法一样,不说了。
不过要注意细节,两个新加节点向上更新的时候不要影响结果,因为答案可能是负数所以要初始化为-INF。
区间反转要交换当前点的lx和rx。
本题空间吃紧,要回收空间,所以删除操作变得很慢(要一个点一个点删除)。把删除的点的空间压入栈内,然后取栈中元素继续利用。
不得不说恶心人的splay可以告一段落了,这题模板题可以一天一遍233
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int SZ = 1000010;
const int INF = 1000000010;
struct node{
node *f,*ch[2];
int v,sz,cnt,sum,lx,rx,mx;
bool same,rev;
void setc(node *x,int d) { (ch[d] = x) -> f = this; }
int dir() { return f -> ch[1] == this; }
void pushdown();
void maintain()
{
sz = ch[0] -> sz + ch[1] -> sz + cnt;
sum = ch[0] -> sum + ch[1] -> sum + v;
lx = max(ch[0] -> lx,ch[0] -> sum + v + max(ch[1] -> lx,0));
rx = max(ch[1] -> rx,ch[1] -> sum + v + max(ch[0] -> rx,0));
mx = max(max(ch[0] -> mx,ch[1] -> mx),max(ch[0] -> rx,0) + v + max(ch[1] -> lx,0));
}
}T[SZ], *root, *null;
int sa[SZ],Tcnt1 = 0,Tcnt2 = 0;
int num[SZ];
node* newnode(int v,node *f)
{
int cnt;
if(Tcnt2) cnt = sa[Tcnt2 --];
else cnt = Tcnt1++;
node *k = T + cnt;
k -> ch[0] = k -> ch[1] = null;
k -> f = f;
k -> v = k -> sum = k -> lx = k -> rx = k -> mx = v;
k -> sz = k -> cnt = 1;
k -> same = k -> rev = 0;
return k;
}
void pushdrev(node *p)
{
if(p == null) return ;
swap(p -> ch[0],p -> ch[1]);
swap(p -> lx,p -> rx);
p -> rev ^= 1;
}
void pushdsame(node *p,int v)
{
if(p == null) return ;
p -> same = 1;
p -> sum = v * p -> sz;
p -> v = v;
p -> mx = p -> lx = p -> rx = max(v,p -> sum);
}
void node::pushdown()
{
if(this == null) return ;
if(rev)
{
pushdrev(ch[0]);
pushdrev(ch[1]);
rev = 0;
}
if(same)
{
pushdsame(ch[0],v);
pushdsame(ch[1],v);
same = 0;
}
}
void rotate(node *p)
{
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p,fa -> dir());
fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
p -> setc(fa,d ^ 1); p -> maintain();
if(fa == root) root = p;
}
void splay(node *p,node *rt = null)
{
p -> pushdown();
while(p -> f != rt)
{
if(p -> f -> f == rt) rotate(p);
else
{
p -> f -> f -> pushdown(); p -> f -> pushdown(); p -> pushdown();
if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
else rotate(p),rotate(p);
}
}
p -> maintain();
}
node* find(node *p,int k)
{
while(p != null)
{
p -> pushdown();
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p;
if(k > r) k -= r,p = p -> ch[1];
else p = p -> ch[0];
}
}
void build(node* &p,int l,int r,node *fa)
{
if(l > r) return ;
int mid = (l + r) >> 1;
p = newnode(num[mid],fa);
build(p -> ch[0],l,mid - 1,p);
build(p -> ch[1],mid + 1,r,p);
p -> maintain();
}
void insert(int pos,int tot)
{
pos ++;
for(int i = 1;i <= tot;++ i) scanf("%d",&num[i]);
splay(find(root,pos)); splay(find(root,pos + 1),root);
build(root -> ch[1] -> ch[0],1,tot,root -> ch[1]);
root -> ch[1] -> maintain();
root -> maintain();
}
void dfs(node *p)
{
if(p == null) return ;
sa[++ Tcnt2] = p - T;
dfs(p -> ch[0]);
dfs(p -> ch[1]);
}
void erase(int l,int r)
{
l ++,r ++;
splay(find(root,l - 1)); splay(find(root,r + 1),root);
dfs(root -> ch[1] -> ch[0]);
root -> ch[1] -> ch[0] = null;
root -> ch[1] -> maintain();
root -> maintain();
}
void change(int l,int r,int v)
{
l ++,r ++;
splay(find(root,l - 1)); splay(find(root,r + 1),root);
pushdsame(root -> ch[1] -> ch[0],v);
root -> ch[1] -> maintain();
root -> maintain();
}
void reverse(int l,int r)
{
l ++,r ++;
splay(find(root,l - 1)); splay(find(root,r + 1),root);
pushdrev(root -> ch[1] -> ch[0]);
root -> ch[1] -> maintain();
root -> maintain();
}
int ask_sum(int l,int r)
{
l ++,r ++;
splay(find(root,l - 1)); splay(find(root,r + 1),root);
return root -> ch[1] -> ch[0] -> sum;
}
int ask_ans(int l,int r)
{
l ++,r ++;
splay(find(root,l - 1)); splay(find(root,r + 1),root);
return root -> ch[1] -> ch[0] -> mx;
}
void init()
{
null = newnode(-INF,null);
null -> cnt = null -> sz = 0;
root = newnode(-INF,null);
root -> ch[1] = newnode(-INF,root);
root -> sum = null -> sum = root -> ch[1] -> sum = 0;
root -> maintain();
}
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
init();
insert(0,n);
while(m --)
{
char in[20];
scanf("%s",in);
if(in[2] == 'S')
{
int pos,tot;
scanf("%d%d",&pos,&tot);
insert(pos,tot);
}
else if(in[2] == 'L')
{
int pos,tot;
scanf("%d%d",&pos,&tot);
int l = pos,r = pos + tot - 1;
erase(l,r);
}
else if(in[2] == 'K')
{
int pos,tot,c;
scanf("%d%d%d",&pos,&tot,&c);
int l = pos,r = pos + tot - 1;
change(l,r,c);
}
else if(in[2] == 'V')
{
int pos,tot;
scanf("%d%d",&pos,&tot);
int l = pos,r = pos + tot - 1;
reverse(l,r);
}
else if(in[2] == 'T')
{
int pos,tot;
scanf("%d%d",&pos,&tot);
int l = pos,r = pos + tot - 1;
printf("%d\n",ask_sum(l,r));
}
else
{
printf("%d\n",ask_ans(1,root -> sz - 2));
}
}
return 0;
}
12.30:
今天换了种打法,把splay的各种操作放到一个结构体里了,这样以后维护多棵splay就方便许多,码量也并没有加几行
需要注意的是需要先初始化null
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int SZ = 1000010;
const int INF = 1000000010;
struct node{
node *ch[2],*f;
int sz,v,cnt,sum,lx,rx,mx;
bool same,rev;
void maintain()
{
sz = ch[0] -> sz + ch[1] -> sz + cnt;
sum = ch[0] -> sum + ch[1] -> sum + v;
lx = max(ch[0] -> lx,ch[0] -> sum + v + max(0,ch[1] -> lx));
rx = max(ch[1] -> rx,ch[1] -> sum + v + max(0,ch[0] -> rx));
mx = max(max(ch[0] -> mx,ch[1] -> mx),max(0,ch[0] -> rx) + v + max(0,ch[1] -> lx));
}
void pushdown();
void setc(node *x,int d) { (ch[d] = x) -> f = this; }
int dir() { return f -> ch[1] == this; }
}T[SZ], *null;
int sa[SZ],Tcnt1 = 0,Tcnt2 = 0;
node* newnode(int x,node *fa)
{
int cnt;
if(Tcnt2) cnt = sa[Tcnt2 --];
else cnt = Tcnt1 ++;
node *k = T + cnt;
k -> ch[0] = k -> ch[1] = null;
k -> v = k -> lx = k -> rx = k -> mx = k -> sum = x;
k -> sz = k -> cnt = 1;
k -> f = fa;
k -> same = k -> rev = 0;
return k;
}
void pushsame(node *p,int v)
{
if(p == null) return ;
p -> v = v;
p -> sum = v * p -> sz;
p -> mx = p -> lx = p -> rx = max(v,p -> sum);
p -> same = 1;
}
void pushrev(node *p)
{
if(p == null) return ;
swap(p -> ch[0],p -> ch[1]);
swap(p -> lx,p -> rx);
p -> rev ^= 1;
}
void node :: pushdown()
{
if(same)
{
pushsame(ch[0],v); pushsame(ch[1],v);
same = 0;
}
if(rev)
{
pushrev(ch[0]); pushrev(ch[1]);
rev = 0;
}
}
int num[SZ];
struct Splaytree{
node *root;
Splaytree()
{
root = newnode(-INF,null);
root -> ch[1] = newnode(-INF,root);
root -> ch[1] -> maintain();
root -> maintain();
}
void rotate(node *p)
{
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p,fa -> dir());
fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
p -> setc(fa,d ^ 1); p -> maintain();
if(fa == root) root = p;
}
void splay(node *p,node *rt = null)
{
p -> pushdown();
while(p -> f != rt)
{
if(p -> f -> f == rt) rotate(p);
else
{
p -> f -> f -> pushdown(); p -> f -> pushdown(); p -> pushdown();
if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
else rotate(p),rotate(p);
}
}
p -> maintain();
}
node* find(node *p,int k)
{
while(p != null)
{
p -> pushdown();
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p;
if(k > r) k -= r,p = p -> ch[1];
else p = p -> ch[0];
}
}
void build(node* &p,int l,int r,node *fa)
{
if(l > r) return ;
int mid = (l + r) >> 1;
p = newnode(num[mid],fa);
build(p -> ch[0],l,mid - 1,p);
build(p -> ch[1],mid + 1,r,p);
p -> maintain();
}
void insert(int pos,int tot)
{
for(int i = 1;i <= tot;i ++) scanf("%d",&num[i]);
splay(find(root,pos + 1)); splay(find(root,pos + 2),root);
build(root -> ch[1] -> ch[0],1,tot,root -> ch[1]);
root -> ch[1] -> maintain();
root -> maintain();
}
void del(node *p)
{
if(p == null) return ;
sa[++ Tcnt2] = p - T;
del(p -> ch[0]);
del(p -> ch[1]);
}
void erase(int pos,int tot)
{
splay(find(root,pos)); splay(find(root,pos + tot + 1),root);
del(root -> ch[1] -> ch[0]);
root -> ch[1] -> ch[0] = null;
root -> ch[1] -> maintain();
root -> maintain();
}
void change(int pos,int tot,int v)
{
splay(find(root,pos)); splay(find(root,pos + tot + 1),root);
pushsame(root -> ch[1] -> ch[0],v);
root -> ch[1] -> maintain();
root -> maintain();
}
void reverse(int pos,int tot)
{
splay(find(root,pos)); splay(find(root,pos + tot + 1),root);
pushrev(root -> ch[1] -> ch[0]);
root -> ch[1] -> maintain();
root -> maintain();
}
int ask_sum(int pos,int tot)
{
splay(find(root,pos)); splay(find(root,pos + tot + 1),root);
return root -> ch[1] -> ch[0] -> sum;
}
int ask_ans()
{
return root -> mx;
}
};
void init()
{
null = newnode(-INF,null);
null -> sum = 0;
null -> sz = null -> cnt = 0;
}
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
init();
Splaytree s;
s.insert(0,n);
while(m --)
{
char opt[10];
int pos,tot;
scanf("%s",opt);
if(opt[2] == 'S')
{
scanf("%d%d",&pos,&tot);
s.insert(pos,tot);
}
else if(opt[2] == 'L')
{
scanf("%d%d",&pos,&tot);
s.erase(pos,tot);
}
else if(opt[2] == 'K')
{
int v;
scanf("%d%d%d",&pos,&tot,&v);
s.change(pos,tot,v);
}
else if(opt[2] == 'V')
{
scanf("%d%d",&pos,&tot);
s.reverse(pos,tot);
}
else if(opt[2] == 'T')
{
scanf("%d%d",&pos,&tot);
printf("%d\n",s.ask_sum(pos,tot));
}
else
{
printf("%d\n",s.ask_ans());
}
}
return 0;
}