bzoj1500 维修数列 splay
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1500 维修数列 splay相关的知识,希望对你有一定的参考价值。
1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 10482 Solved: 3234
[Submit][Status][Discuss]
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
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
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
10
1
10
HINT
终于过了,原来是维护最大子序列合并的时候写错了。。。应该是当前结点最大子序列和等于max(左子结点最大子序列,和右子结点最大子序列,横跨左右的最大子序列和),我居然写成了max(包括左端点的最大子序列,包括右端点的最大子序列,.....)。。。。。
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define key_val ch[ch[rt][1]][0] using namespace std; typedef long long ll; const int maxn=500100; const int INF=1e9+10; const ll MOD=1e9+7; int N,M; int a[maxn]; char op[20];int pos,n; int c[maxn]; int pre[maxn],sz[maxn],ch[maxn][2],rt,tot1; int s[maxn],tot2; int sum[maxn],val[maxn]; int ls[maxn],rs[maxn],ms[maxn]; int cov[maxn],rev[maxn]; int newnode(int &r,int fa,int k) { if(tot2) r=s[tot2--]; else r=++tot1; pre[r]=fa;val[r]=k; sz[r]=1;MS0(ch[r]); sum[r]=k; cov[r]=rev[r]=0; ls[r]=ms[r]=rs[r]=k; } void update_rev(int r) { if(r==0) return; rev[r]^=1; swap(ch[r][0],ch[r][1]); swap(ls[r],rs[r]); } void update_cov(int r,int c) { if(r==0) return; cov[r]=1; sum[r]=c*sz[r]; val[r]=c; ls[r]=rs[r]=ms[r]=max(c,c*sz[r]); } void down(int r) { if(rev[r]){ update_rev(ch[r][0]); update_rev(ch[r][1]); rev[r]=0; } if(cov[r]){ update_cov(ch[r][0],val[r]); update_cov(ch[r][1],val[r]); cov[r]=0; } } void up(int r) { sz[r]=sz[ch[r][0]]+sz[ch[r][1]]+1; sum[r]=sum[ch[r][0]]+sum[ch[r][1]]+val[r]; ls[r]=max(ls[ch[r][0]],sum[ch[r][0]]+val[r]+max(0,ls[ch[r][1]])); rs[r]=max(rs[ch[r][1]],sum[ch[r][1]]+val[r]+max(0,rs[ch[r][0]])); ms[r]=val[r]+max(rs[ch[r][0]],0)+max(ls[ch[r][1]],0); ms[r]=max(ms[r],max(ms[ch[r][0]],ms[ch[r][1]])); } void rot(int x,int kind) { int y=pre[x]; down(y);down(x); ch[y][kind^1]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; up(y); } void splay(int x,int goal) { down(x); while(pre[x]!=goal){ if(pre[pre[x]]==goal) rot(x,ch[pre[x]][0]==x); else{ int y=pre[x],z=pre[y]; int kind=ch[y][0]==x,one=0; if(ch[y][0]==x&&ch[z][0]==y) one=1; if(ch[y][1]==x&&ch[z][1]==y) one=1; if(one) rot(y,kind),rot(x,kind); else rot(x,kind),rot(x,kind^1); } } if(goal==0) rt=x; up(x); } void rto(int k,int goal) { int r=rt;k++; while(k!=sz[ch[r][0]]+1){ down(r); if(k<sz[ch[r][0]]+1) r=ch[r][0]; else k-=sz[ch[r][0]]+1,r=ch[r][1]; } splay(r,goal); } void build(int &x,int l,int r,int fa,int *a) { if(l>r) return; int m=(l+r)>>1; newnode(x,fa,a[m]); build(ch[x][0],l,m-1,x,a); build(ch[x][1],m+1,r,x,a); up(x); } void Init() { pre[0]=sz[0]=s[0]=0;MS0(ch[0]);rt=tot1=tot2=0; sum[0]=val[0]=cov[0]=rev[0]=0; ls[0]=rs[0]=ms[0]=-INF; newnode(rt,0,-1); newnode(ch[rt][1],rt,-1); sz[rt]=2; build(key_val,1,N,ch[rt][1],a); up(ch[rt][1]);up(rt); } void Rev(int l,int r) { rto(l-1,0); rto(r+1,rt); down(rt);down(ch[rt][1]); update_rev(key_val); up(ch[rt][1]);up(rt); } void Cov(int l,int r,int c) { rto(l-1,0); rto(r+1,rt); down(rt);down(ch[rt][1]); update_cov(key_val,c); up(ch[rt][1]);up(rt); } void Erase(int r) { if(r==0) return; s[++tot2]=r; Erase(ch[r][0]); Erase(ch[r][1]); } void Del(int l,int r) { rto(l-1,0); rto(r+1,rt); down(rt);down(ch[rt][1]); Erase(key_val); key_val=0; up(ch[rt][1]);up(rt); } void Insert(int pos,int n) { rto(pos,0); rto(pos+1,rt); down(rt);down(ch[rt][1]); build(key_val,1,n,ch[rt][1],c); up(ch[rt][1]);up(rt); } int Sum(int l,int r) { if(l>r) return 0; rto(l-1,0); rto(r+1,rt); down(rt);down(ch[rt][1]); return sum[key_val]; } int Max_sum() { int l=1,r=sz[rt]-2; if(l>r) return 0; rto(l-1,0); rto(r+1,rt); down(rt);down(ch[rt][1]); return ms[key_val]; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d%d",&N,&M)){ REP(i,1,N) scanf("%d",&a[i]); Init(); //out(); REP(i,1,M){ scanf("%s",&op); if(op[0]==‘I‘){ scanf("%d%d",&pos,&n); REP(j,1,n) scanf("%d",&c[j]); Insert(pos,n); } else if(op[0]==‘D‘){ scanf("%d%d",&pos,&n); Del(pos,pos+n-1); } else if(op[0]==‘M‘&&op[2]==‘K‘){ scanf("%d%d%d",&pos,&n,&c[0]); Cov(pos,pos+n-1,c[0]); } else if(op[0]==‘R‘){ scanf("%d%d",&pos,&n); Rev(pos,pos+n-1); } else if(op[0]==‘G‘){ scanf("%d%d",&pos,&n); printf("%d\n",Sum(pos,pos+n-1)); } else printf("%d\n",Max_sum()); } } return 0; }
以上是关于bzoj1500 维修数列 splay的主要内容,如果未能解决你的问题,请参考以下文章