[NOI2005]维护数列
bzoj1500 [NOI2005]维护数列
题目描述:
请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)
输入输出格式
输入格式:
输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。 第 2 行包含 N 个数字,描述初始时的数列。 以下 M 行,每行一条命令,格式参见问题描述中的表格
输出格式:
对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结 果,每个答案(数字)占一行。
输入输出样例
输入样例#1:
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:
-1
10
1
10
说明
你可以认为在任何时刻,数列中至少有 1 个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有 30 000 个数;
100%的数据中,任何时刻数列中最多含有 500 000 个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。
题解:
对于前5个操作,直接按照splay操作进行
第6个操作,记录左起最长序列、右起最长序列和这个区间的最长序列,合并时通过左右合并
为防止MLE,需要把树上被删除节点回收
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<bitset>
#include<sstream>
#include<cstdlib>
#define QAQ int
#define TAT long long
#define OwO bool
#define ORZ double
#define F(i,j,n) for(QAQ i=j;i<=n;++i)
#define E(i,j,n) for(QAQ i=j;i>=n;--i)
#define MES(i,j) memset(i,j,sizeof(i))
#define MEC(i,j) memcpy(i,j,sizeof(j))
using namespace std;
const QAQ N=1000010;
const QAQ Big=1e6;
QAQ n,m,js,rot,a[N>>1],id[N>>1];
struct data{
QAQ fa,son[2],sum;
QAQ val,size,mx,lx,rx;
OwO rev,lset;
}tree[N];
queue<QAQ> q;
char s[15];
void push_up(QAQ o){
QAQ l=tree[o].son[0],r=tree[o].son[1];
tree[o].sum=tree[l].sum+tree[r].sum+tree[o].val;
tree[o].size=tree[l].size+tree[r].size+1;
tree[o].mx=max(max(tree[l].mx,tree[r].mx),tree[l].rx+tree[r].lx+tree[o].val);
tree[o].lx=max(tree[l].lx,tree[l].sum+tree[r].lx+tree[o].val);
tree[o].rx=max(tree[r].rx,tree[r].sum+tree[l].rx+tree[o].val);
}
void push_down(QAQ o){
QAQ l=tree[o].son[0],r=tree[o].son[1];
if(tree[o].lset){
tree[o].lset=tree[o].rev=0;
if(l) {tree[l].lset=1;tree[l].val=tree[o].val;tree[l].sum=tree[l].size*tree[l].val;}
if(r) {tree[r].lset=1;tree[r].val=tree[o].val;tree[r].sum=tree[r].size*tree[r].val;}
if(tree[o].val>=0){
if(l) tree[l].lx=tree[l].rx=tree[l].mx=tree[l].sum;
if(r) tree[r].lx=tree[r].rx=tree[r].mx=tree[r].sum;
}
else {
if(l) tree[l].lx=tree[l].rx=0,tree[l].mx=tree[l].val;
if(r) tree[r].lx=tree[r].rx=0,tree[r].mx=tree[r].val;
}
}
if(tree[o].rev){
tree[o].rev=0;tree[l].rev^=1;tree[r].rev^=1;
swap(tree[l].lx,tree[l].rx);swap(tree[r].lx,tree[r].rx);
swap(tree[l].son[0],tree[l].son[1]);
swap(tree[r].son[0],tree[r].son[1]);
}
}
void build(QAQ l,QAQ r,QAQ fa){
if(l>r) return ;
QAQ mid=l+r>>1,o=id[mid];
if(l==r){
tree[o].mx=tree[o].sum=a[l];
tree[o].lset=tree[o].rev=0;
tree[o].lx=tree[o].rx=max(a[l],0);
tree[o].size=1;
}
build(l,mid-1,mid);build(mid+1,r,mid);
tree[o].val=a[mid];tree[o].fa=id[fa];
push_up(o);
tree[id[fa]].son[mid>=fa]=o;
}
QAQ find(QAQ o,QAQ x){
push_down(o);
if(tree[tree[o].son[0]].size+1==x) return o;
else if(tree[tree[o].son[0]].size>=x) return find(tree[o].son[0],x);
else return find(tree[o].son[1],x-tree[tree[o].son[0]].size-1);
}
OwO get(QAQ o){return tree[tree[o].fa].son[1]==o;}
void rotate(QAQ o){
QAQ fa=tree[o].fa,ff=tree[fa].fa;
OwO pd=get(o);
if(ff) tree[ff].son[get(fa)]=o;
tree[o].fa=ff;
tree[fa].son[pd]=tree[o].son[1-pd];
tree[tree[o].son[1-pd]].fa=fa;
tree[fa].fa=o;tree[o].son[1-pd]=fa;
push_up(fa);push_up(o);
}
void splay(QAQ o,QAQ goal){
while(tree[o].fa!=goal){
QAQ fa=tree[o].fa,ff=tree[fa].fa;
if(ff!=goal) if(tree[ff].son[1]==fa ^ tree[fa].son[1]==o) rotate(o);
else rotate(fa);
rotate(o);
}
if(!goal) rot=o;
push_up(o);
}
void Insert(QAQ p,QAQ tot){
F(i,1,tot) scanf("%d",&a[i]);
F(i,1,tot) if(q.size()) id[i]=q.front(),q.pop();
else id[i]=++js;
build(1,tot,0);
QAQ l=find(rot,p+1),r=find(rot,p+2);
splay(l,0);splay(r,l);
QAQ rt=id[1+tot>>1];
tree[rt].fa=r;tree[r].son[0]=rt;
push_up(r);push_up(l);
}
QAQ split(QAQ p,QAQ tot){
QAQ l=find(rot,p),r=find(rot,p+tot+1);
splay(l,0);
splay(r,l);
return tree[r].son[0];
}
void recovery(QAQ o){
if(tree[o].son[0]) recovery(tree[o].son[0]);
if(tree[o].son[1]) recovery(tree[o].son[1]);
q.push(o);
tree[o].fa=tree[o].son[0]=tree[o].son[1]=tree[o].lset=tree[o].rev=0;
}
void Del(QAQ p,QAQ tot){
QAQ o=split(p,tot);
QAQ fa=tree[o].fa;
recovery(o);
tree[fa].son[0]=0;
push_up(fa);push_up(tree[fa].fa);
}
void change(QAQ p,QAQ tot,QAQ x){
QAQ o=split(p,tot);
tree[o].val=x;tree[o].lset=1;
tree[o].sum=tree[o].val*tree[o].size;
if(tree[o].val>=0) tree[o].lx=tree[o].rx=tree[o].mx=tree[o].sum;
else tree[o].lx=tree[o].rx=0,tree[o].mx=tree[o].val;
push_up(tree[o].fa);push_up(tree[tree[o].fa].fa);
}
void reverse(QAQ p,QAQ tot){
QAQ o=split(p,tot);
if(!tree[o].lset){
tree[o].rev^=1;
swap(tree[o].son[0],tree[o].son[1]);
swap(tree[o].lx,tree[o].rx);
push_up(tree[o].fa);
push_up(tree[tree[o].fa].fa);
}
}
QAQ get_sum(QAQ p,QAQ tot){
QAQ o=split(p,tot);
return tree[o].sum;
}
QAQ main(){
scanf("%d%d",&n,&m);
F(i,2,n+1) scanf("%d",&a[i]),id[i]=i;
tree[0].mx=a[1]=a[n+2]=-Big;
id[1]=1;id[n+2]=n+2;
build(1,n+2,0);
rot=n+3>>1;js=n+2;
while(m--){
scanf("%s",s+1);
if(s[1]=='I'){
QAQ p,tot;
scanf("%d%d",&p,&tot);
Insert(p,tot);
}
else if(s[1]=='D'){
QAQ p,tot;
scanf("%d%d",&p,&tot);
Del(p,tot);
}
else if(s[1]=='M'&&s[3]=='K'){
QAQ p,tot,x;
scanf("%d%d%d",&p,&tot,&x);
change(p,tot,x);
}
else if(s[1]=='R'){
QAQ p,tot;
scanf("%d%d",&p,&tot);
reverse(p,tot);
}
else if(s[1]=='G'){
QAQ p,tot;
scanf("%d%d",&p,&tot);
printf("%d\n",get_sum(p,tot));
}
else printf("%d\n",tree[rot].mx);
}
return 0;
}