早已膜拜过这等数据结构神题。一直没下定决心做。于是今天终于下定决心要把它A掉。
14:39 我要把这道题搞出来!
以前看到这道题的时候一直纠结建树的时候都是按下标建的。可是现在中间会插入删除,下标没法存了肿么破。
结果其实从根下去根据size找第几个就行了。真是太弱了。然后就可做了。
15:38 程序码完了..不管怎样编译过了。虽然样例还没试。但是很激动的赶脚。
15:39 开始调试样例。调了几下欣喜若狂以为对了。(我竟然没发现有一个输出是1我输出的是0)
15:59 我激动的交上OJ,结果是T?!
然后是各种对拍。各种输出。各种眼花。各种绝望。
17:32 改了改,还是T?!
然后就是一直一直不停的调。。始终发现不了问题在哪。。
18:09 从szy大神那要来了数据。感谢。(是的我调了这么久了)
然后我发现除了第一个点后面都T了。受不了了。我写的splay这么渣?
后来绝望了就先去吃饭了。
20:21 回来继续调,发现了从根降下去的时候没有pushdown!
改过来有90分了!其实我本来想交上OJ的。因为自己机子本身就不快,交到OJ上应该可以A的。
不过想想还是加了个读入优化。果然,轻松100。
于是——
真是各种兴奋。
从开始写到正式A掉花了六个小时。调的时间比写的时间多多了。唉真是弱逼。
不过终于把这道神题A掉了。算是对自己的平衡树学习的一个交代吧。
写的过程中发现了几处要注意的地方:
1.从根下降的时候要先pushdown。。唉真是太弱了。。T.T这都会忘。。那么久还没发现。。
2.求最大连续子串和的时候,初始max要置为-inf而不是0。因为有可能答案就是负数。这点在GSS系列中曾经吃过苦头>.<
3.开个垃圾回收吧。不然有可能爆内存的说。(虽然我没试过D)
4.区分这几个操作的单词时。可以比较它们第3个字母。发现它们是各不相同的。呵呵。不过想怎么弄就怎么弄。呵呵。
贴上代码。我会说这是我写到现在为止最长的一个程序?(Q:你煞笔吧。这就最长了?A:我的确是煞笔。。)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 500005
int n,q,a[maxn];
struct SplayTree{
#define S 500005
#define inf 100000009
int ch[S][2],fa[S],val[S],sz[S],rev[S],same[S],sum[S],lmax[S],rmax[S],smax[S],pool[S],rt,tot,poolcnt;
#define ls ch[x][0]
#define rs ch[x][1]
#define key ch[ch[rt][1]][0]
#define SPLAY rto(pos,0);rto(pos+k+1,rt)
inline void sw(int &a,int &b){ a^=b; b^=a; a^=b; }
inline void newnode(int &x,int k,int f){
if(poolcnt) x=pool[poolcnt--]; else x=++tot;
ls=rs=rev[x]=same[x]=0;
fa[x]=f;sz[x]=1;
val[x]=sum[x]=lmax[x]=rmax[x]=smax[x]=k;
}
inline void rotate(int x,int f){
int y=fa[x];
pushdown(y);
pushdown(x);
ch[y][!f]=ch[x][f];
fa[ch[x][f]]=y;
if(fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[x]=fa[y];
ch[x][f]=y;
fa[y]=x;
pushup(y);
}
inline void splay(int x,int goal){
pushdown(x);
while(fa[x]!=goal){
if(fa[fa[x]]==goal) rotate(x,ch[fa[x]][0]==x);
else{
int y=fa[x],z=fa[y];
int f=(ch[z][0]==y);
if(ch[y][f]==x) rotate(x,!f),rotate(x,f);
else rotate(y,f),rotate(x,f);
}
}
pushup(x);
if(goal==0)rt=x;
}
inline void rto(int k,int goal){
int x=rt;
pushdown(x);
while(sz[ls]+1!=k){
if(k<sz[ls]+1) x=ls;
else k-=(sz[ls]+1),x=rs;
pushdown(x);
}
splay(x,goal);
}
inline void updsame(int x,int v){
if(!x) return;
same[x]=1;
val[x]=v;
sum[x]=sz[x]*v;
lmax[x]=rmax[x]=smax[x]=max(v,v*sz[x]);
}
inline void updrev(int x){
if(!x) return;
sw(ls,rs); sw(lmax[x],rmax[x]);
rev[x]^=1;
}
inline void pushup(int x){
sz[x]=sz[ls]+sz[rs]+1;
sum[x]=sum[ls]+sum[rs]+val[x];
lmax[x]=max(lmax[ls],sum[ls]+val[x]+max(0,lmax[rs]));
rmax[x]=max(rmax[rs],sum[rs]+val[x]+max(0,rmax[ls]));
smax[x]=max(max(smax[ls],smax[rs]),max(0,rmax[ls])+val[x]+max(0,lmax[rs]));
}
inline void pushdown(int x){
if(rev[x]) updrev(ls),updrev(rs),rev[x]=0;
if(same[x]) updsame(ls,val[x]),updsame(rs,val[x]),same[x]=0;
}
inline void build(int &x,int l,int r,int f){
if(l>r) return;
int mid=(l+r)>>1;
newnode(x,a[mid],f);
build(ls,l,mid-1,x);
build(rs,mid+1,r,x);
pushup(x);
}
inline void init(){
tot=poolcnt=rt=0;
ch[rt][0]=ch[rt][1]=fa[rt]=rev[rt]=same[rt]=sz[rt]=sum[rt]=0;
lmax[rt]=rmax[rt]=smax[rt]=-inf;
newnode(rt,-1,0);
newnode(ch[rt][1],-1,rt);
pushup(rt);
build(key,1,n,ch[rt][1]);
pushup(ch[rt][1]);
pushup(rt);
}
inline int getnum(int k){
int x=rt;
pushdown(x);
while(sz[ls]+1!=k){
if(k<sz[ls]+1) x=ls;
else k-=(sz[ls]+1),x=rs;
pushdown(x);
}
return x;
}
inline int getmin(int x){
pushdown(x);
while(ls) x=ls,pushdown(x);
return x;
}
inline void ins(int pos,int k){
int x=getnum(pos);
splay(x,0);
int m=getmin(ch[rt][1]);
splay(m,rt);
build(key,1,k,ch[rt][1]);
pushup(ch[rt][1]);
pushup(rt);
}
inline void delone(int x){
if(!x) return;
pool[++poolcnt]=x;
delone(ls); delone(rs);
}
inline void del(int pos,int k){
SPLAY;
delone(key);
fa[key]=0;
key=0;
pushup(ch[rt][1]);
pushup(rt);
}
inline void makesame(int pos,int k,int v){
SPLAY;
updsame(key,v);
pushup(ch[rt][1]);
pushup(rt);
}
inline void reverse(int pos,int k){
SPLAY;
updrev(key);
}
inline int getsum(int pos,int k){
SPLAY;
return sum[key];
}
inline int _getmaxsum(int pos,int k){
SPLAY;
return smax[key];
}
inline int getmaxsum(void){
return _getmaxsum(1,sz[rt]-2);
}
}spt;
inline void read(int &x){
char ch; int f=1;
for(ch=getchar();(ch<'0' || ch>'9')&&(ch!='-');ch=getchar());
if(ch=='-')f=-1,x=0; else x=ch-'0';
for(ch=getchar();ch>='0' && ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
int main()
{
//freopen("sequence.in","r",stdin);
//freopen("sequence.out","w",stdout);
read(n); read(q);
for(int i=1;i<=n;i++) read(a[i]);
spt.init();
char op[10];
int pos,k,v;
while(q--){
scanf("%s",op);
if(op[2]=='S'){
read(pos); read(k);
for(int i=1;i<=k;i++) read(a[i]);
spt.ins(pos+1,k);
}else if(op[2]=='L'){
read(pos); read(k);
spt.del(pos,k);
}else if(op[2]=='K'){
read(pos); read(k); read(v);
spt.makesame(pos,k,v);
}else if(op[2]=='V'){
read(pos); read(k);
spt.reverse(pos,k);
}else if(op[2]=='T'){
read(pos); read(k);
printf("%d\n",spt.getsum(pos,k));
}else printf("%d\n",spt.getmaxsum());
}
return 0;
}
做完这题就可以把GSS6(要求支持操作:插入一个数、删除一个数、修改一个数、询问最大连续子段和)轻松A掉了。虽然我A的很不轻松。我竟然没发现newnode的时候size没设成1。= =真是奇葩。这道题一开始我也没写但是却过了。于是现在我把这句加上了。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 300005
int n,q,a[maxn];
struct SplayTree{
#define S 300005
#define inf 100000009
int ch[S][2],fa[S],val[S],sz[S],sum[S],lmax[S],rmax[S],smax[S],pool[S],rt,tot,poolcnt;
#define ls ch[x][0]
#define rs ch[x][1]
#define key ch[ch[rt][1]][0]
inline void sw(int &a,int &b){ a^=b; b^=a; a^=b; }
inline void newnode(int &x,int k,int f){
if(poolcnt) x=pool[poolcnt--]; else x=++tot;
sz[x]=1;
ls=rs=0;
fa[x]=f;
val[x]=sum[x]=lmax[x]=rmax[x]=smax[x]=k;
}
inline void rotate(int x,int f){
int y=fa[x];
ch[y][!f]=ch[x][f];
fa[ch[x][f]]=y;
if(fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[x]=fa[y];
ch[x][f]=y;
fa[y]=x;
pushup(y);
}
inline void splay(int x,int goal){
while(fa[x]!=goal){
if(fa[fa[x]]==goal) rotate(x,ch[fa[x]][0]==x);
else{
int y=fa[x],z=fa[y];
int f=(ch[z][0]==y);
if(ch[y][f]==x) rotate(x,!f),rotate(x,f);
else rotate(y,f),rotate(x,f);
}
}
pushup(x);
if(goal==0)rt=x;
}
inline void rto(int k,int goal){
int x=rt;
while(sz[ls]+1!=k){
if(k<sz[ls]+1) x=ls;
else k-=(sz[ls]+1),x=rs;
}
splay(x,goal);
}
inline void pushup(int x){
sz[x]=sz[ls]+sz[rs]+1;
sum[x]=sum[ls]+sum[rs]+val[x];
lmax[x]=max(lmax[ls],sum[ls]+val[x]+max(0,lmax[rs]));
rmax[x]=max(rmax[rs],sum[rs]+val[x]+max(0,rmax[ls]));
smax[x]=max(max(smax[ls],smax[rs]),max(0,rmax[ls])+val[x]+max(0,lmax[rs]));
}
inline void build(int &x,int l,int r,int f){
if(l>r) return;
int mid=(l+r)>>1;
newnode(x,a[mid],f);
build(ls,l,mid-1,x);
build(rs,mid+1,r,x);
pushup(x);
}
inline void init(){
tot=poolcnt=rt=0;
ch[rt][0]=ch[rt][1]=fa[rt]=sz[rt]=sum[rt]=0;
lmax[rt]=rmax[rt]=smax[rt]=-inf;
newnode(rt,-1,0);
newnode(ch[rt][1],-1,rt);
pushup(rt);
build(key,1,n,ch[rt][1]);
pushup(ch[rt][1]);
pushup(rt);
}
inline int getnum(int k){
int x=rt;
while(sz[ls]+1!=k){
if(k<sz[ls]+1) x=ls;
else k-=(sz[ls]+1),x=rs;
}
return x;
}
inline int getmin(int x){
while(ls) x=ls;
return x;
}
inline void ins(int pos){
rto(pos,0);
rto(pos+1,rt);
newnode(key,a[1],ch[rt][1]);
pushup(key);
pushup(ch[rt][1]);
pushup(rt);
}
inline void del(int pos){
rto(pos,0);
rto(pos+2,rt);
pool[++poolcnt]=key;
fa[key]=0;
key=0;
pushup(ch[rt][1]);
pushup(rt);
}
inline void change(int pos,int v){
rto(pos,0);
rto(pos+2,rt);
val[key]=v;
pushup(ch[rt][1]);
pushup(rt);
splay(key,0);
}
inline int getmaxsum(int pos,int k){
rto(pos,0);
rto(pos+k+1,rt);
return smax[key];
}
}spt;
inline void read(int &x){
char ch; int f=1;
for(ch=getchar();(ch<'0' || ch>'9')&&(ch!='-');ch=getchar());
if(ch=='-')f=-1,x=0; else x=ch-'0';
for(ch=getchar();ch>='0' && ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
int main()
{
read(n);
for(int i=1;i<=n;i++) read(a[i]);
spt.init();
char op[2];
int pos,v;
read(q);
while(q--){
scanf("%s",op);
if(op[0]=='I'){
read(pos); read(a[1]);
spt.ins(pos);
}else if(op[0]=='D'){
read(pos);
spt.del(pos);
}else if(op[0]=='R'){
read(pos); read(v);
spt.change(pos,v);
}else{
read(pos); read(v);
printf("%d\n",spt.getmaxsum(pos,v-pos+1));
}
}
return 0;
}