bzoj1500 [NOI2005]维修数列
题目链接:bzoj1500
这是一篇补档博客
讲真,出题人出这种看起来十分模板,几乎没有思维难度,但是细节贼多,考场上几乎不可能写高分的题目出出来的心态是什么
就这个题,前四个操作几乎是清一色的画风——把要操作的东西单独建成一颗平衡树(splay),然后各种左右儿子找
第五个操作直接维护,第六个类似于分治的时候,维护左端点起始最大值、右端点起始最大值、包含该点及其子树的最大值。就做完了,哦,为了内存不炸回收一下delete的节点编号以下次使用
但是细节巨多啊。。。几乎是完全不可能在考场上调出来啊
所以这种题真的只适合养性了吧。。。
献上6k代码
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
using namespace std;
#define int long long
const int maxd=1000000007,N=100000;
const double pi=acos(-1.0);
typedef long long ll;
struct node{
int ch[2],fa,same,rev;
ll sum,lsum,val,rsum,siz,maxsum;
void init(int v)
{
siz=1;val=v;sum=v;
same=0;rev=0;
ch[0]=0;ch[1]=0;
lsum=max(v,0ll);rsum=lsum;maxsum=v;
}
}tree[600000];
queue<int> q;
int n,qsiz,tot=0,root=0,a[600000];
char s[100];
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void pushup(int x)
{
int l=tree[x].ch[0],r=tree[x].ch[1];
tree[x].siz=tree[l].siz+tree[r].siz+1;
tree[x].sum=tree[l].sum+tree[r].sum+tree[x].val;
tree[x].maxsum=max(tree[l].maxsum,max(tree[r].maxsum,tree[l].rsum+tree[x].val+tree[r].lsum));
tree[x].lsum=max(tree[l].lsum,tree[l].sum+tree[x].val+tree[r].lsum);
tree[x].rsum=max(tree[r].rsum,tree[r].sum+tree[x].val+tree[l].rsum);
}
void pushdown(int x)
{
int l=tree[x].ch[0],r=tree[x].ch[1];
if (tree[x].same)
{
tree[x].same=0;tree[x].rev=0;
if (l)
{
tree[l].same=1;tree[l].val=tree[x].val;tree[l].sum=tree[x].val*tree[l].siz;
}
if (r)
{
tree[r].same=1;tree[r].val=tree[x].val;tree[r].sum=tree[x].val*tree[r].siz;
}
if (tree[x].val>=0)
{
if (l) tree[l].lsum=tree[l].rsum=tree[l].maxsum=tree[l].sum;
if (r) tree[r].lsum=tree[r].rsum=tree[r].maxsum=tree[r].sum;
}
else
{
if (l) {tree[l].lsum=0;tree[l].rsum=0;tree[l].maxsum=tree[x].val;}
if (r) {tree[r].lsum=0;tree[r].rsum=0;tree[r].maxsum=tree[x].val;}
}
}
if (tree[x].rev)
{
tree[x].rev^=1;
if (l) tree[l].rev^=1;
if (r) tree[r].rev^=1;
swap(tree[l].lsum,tree[l].rsum);swap(tree[r].lsum,tree[r].rsum);
swap(tree[l].ch[0],tree[l].ch[1]);swap(tree[r].ch[0],tree[r].ch[1]);
}
}
void rotate(int x)
{
int y=tree[x].fa,z=tree[y].fa,k=(tree[y].ch[1]==x);
tree[z].ch[tree[z].ch[1]==y]=x;
tree[x].fa=z;
tree[y].ch[k]=tree[x].ch[k^1];
tree[tree[x].ch[k^1]].fa=y;
tree[x].ch[k^1]=y;tree[y].fa=x;
pushup(y);pushup(x);
}
void splay(int x,int goal)
{
while (tree[x].fa!=goal)
{
int y=tree[x].fa,z=tree[y].fa;
if (z!=goal)
{
if ((tree[y].ch[1]==x)^(tree[z].ch[1]==y)) rotate(x);else rotate(y);
}
rotate(x);
}
if (!goal) root=x;
}
int rnk(int k)
{
int now=root;
//cout << k << endl;
while (now)
{
pushdown(now);
if (tree[tree[now].ch[0]].siz+1<k)
{k-=(tree[tree[now].ch[0]].siz+1);now=tree[now].ch[1];}
else if (tree[tree[now].ch[0]].siz+1==k) return now;
else now=tree[now].ch[0];
//cout << now << " " << k << endl;
}
}
int build(int l,int r,int fa)
{
if (l>r) return 0;
int mid=(l+r)>>1,now=q.front();q.pop();qsiz--;
if (l==r)
{
tree[now].fa=fa;
tree[now].init(a[mid]);
return now;
}
tree[now].val=a[mid];tree[now].maxsum=a[mid];tree[now].fa=fa;
tree[now].ch[0]=build(l,mid-1,now);
tree[now].ch[1]=build(mid+1,r,now);
pushup(now);
return now;
}
void clr(int x)
{
tree[x].maxsum=-maxd;
tree[x].fa=0;tree[x].ch[0]=0;tree[x].ch[1]=0;
tree[x].lsum=0;tree[x].rsum=0;tree[x].siz=0;tree[x].rev=0;
tree[x].same=0;
}
void reuse(int x)
{
if (!x) return;
q.push(x);qsiz++;
if (tree[x].ch[0]) reuse(tree[x].ch[0]);
if (tree[x].ch[1]) reuse(tree[x].ch[1]);
clr(x);
}
void insert()
{
int pos=read(),tot=read(),i;
if (!tot) return;
for (i=1;i<=tot;i++) a[i]=read();
int l=rnk(pos+1),r=rnk(pos+2);
splay(l,0);splay(r,l);
tree[r].ch[0]=build(1,tot,r);
pushup(r);pushup(l);
}
void del()
{
int pos=read(),tot=read();
if (!tot) return;
int l=rnk(pos),r=rnk(pos+tot+1);
//cout << l << " " << r << endl;
splay(l,0);splay(r,l);
reuse(tree[r].ch[0]);
tree[r].ch[0]=0;
pushup(r);pushup(l);
}
void rever()
{
int pos=read(),tot=read();
if (!tot) return;
int l=rnk(pos),r=rnk(pos+tot+1);
splay(l,0);splay(r,l);
int now=tree[r].ch[0];
if (!tree[now].same)
{
tree[now].rev^=1;
swap(tree[now].ch[0],tree[now].ch[1]);
swap(tree[now].lsum,tree[now].rsum);
pushup(r);pushup(l);
}
}
void getsum()
{
int pos=read(),tot=read();
//if (!tot) return;
int l=rnk(pos),r=rnk(pos+tot+1);
splay(l,0);splay(r,l);
printf("%lld\n",tree[tree[r].ch[0]].sum);
}
void makesame()
{
int pos=read(),tot=read(),nowval=read();
//if (!tot) return;
int l=rnk(pos),r=rnk(pos+tot+1);
splay(l,0);splay(r,l);
int now=tree[r].ch[0];
tree[now].val=nowval;tree[now].same=1;tree[now].sum=tree[now].siz*nowval;
if (nowval>=0)
{
tree[now].lsum=tree[now].siz*nowval;
tree[now].rsum=tree[now].lsum;tree[now].maxsum=tree[now].lsum;
}
else
{
tree[now].lsum=0;tree[now].rsum=0;tree[now].maxsum=nowval;
}
pushup(r);pushup(l);
}
void maxsum()
{
printf("%lld\n",tree[root].maxsum);
}
signed main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
n=read();int Q=read(),i;qsiz=505000;
clr(0);
for (i=1;i<=550000;i++) q.push(i);
a[1]=-maxd;a[n+2]=-maxd;
for (i=1;i<=n;i++) a[i+1]=read();
root=build(1,n+2,0);
//for (i=1;i<=n+2;i++) cout << tree[i].sum << " ";cout << endl;
while (Q--)
{
scanf("%s",s);int tot;
if (s[0]=='I') insert();
else if (s[0]=='D') del();
else if (s[0]=='R') rever();
else if (s[0]=='G') getsum();
else if ((s[0]=='M') && (s[2]=='K')) makesame();
else if ((s[0]=='M') && (s[2]=='X')) maxsum();
//for (i=1;i<=20;i++) cout << tree[i].fa << " ";cout << endl;
}
return 0;
}