BZOJ1500:[NOI2005]维修数列
1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 14486 Solved: 4723
[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
思路{
为何发现我的蛋碎了..........
为何发现被维修的不是数列,而是我.........
关键是最后一个操作!
设l[x]为以当前节点所代表的区间左端点为起点的序列最大值,
那么往上传的时候,由于以下标为键值l[x]=Max(l[ls],Sum[ls]+v[x]+l[rs]);
同理更新r[x],设Max[x]为一段区间内最大值,Max[x]在上传的过程中一路更新(很妙啊~~~)
然后就轻巧地用嘴巴AC辣~~~~(调得想死.......)
膜Hzwer的代码咯.
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #include<bits/stdc++.h> #define RG register #define il inline #define N 1000005 #define rs (ch[x][1]) #define ls (ch[x][0]) using namespace std; int ch[N][2],fa[N],sum[N],l[N],r[N],sz[N],v[N],Max[N],rt,id[N],a[N],n,m,cnt; bool tag[N],rev[N]; void up( int x){ sz[x]=sz[ls]+sz[rs]+1; sum[x]=sum[rs]+sum[ls]+v[x]; Max[x]=max(Max[rs],Max[ls]); Max[x]=max(Max[x],v[x]+r[ls]+l[rs]); l[x]=max(l[ls],sum[ls]+v[x]+l[rs]); r[x]=max(r[rs],sum[rs]+v[x]+r[ls]); } void down( int x){ if (tag[x]){ rev[x]=tag[x]=0; if (rs)v[rs]=v[x],sum[rs]=sz[rs]*v[x],tag[rs]=1; if (ls)v[ls]=v[x],sum[ls]=sz[ls]*v[x],tag[ls]=1; if (v[x]>=0){ if (ls)l[ls]=r[ls]=Max[ls]=sum[ls]; if (rs)l[rs]=r[rs]=Max[rs]=sum[rs]; } else { if (ls)l[ls]=r[ls]=0,Max[ls]=v[x]; if (rs)l[rs]=r[rs]=0,Max[rs]=v[x]; } } if (rev[x])rev[x]^=1,rev[rs]^=1,rev[ls]^=1,swap(rs,ls),swap(l[rs],r[rs]),swap(l[ls],r[ls]); } void Rotate( int x, int &k){ int y=fa[x],z=fa[y],l,r; if (z)down(z);down(y),down(x); l=ch[y][1]==x,r=l^1; if (y==k)k=x; else ch[z][ch[z][1]==y]=x; fa[x]=z,fa[y]=x,fa[ch[x][r]]=y;ch[y][l]=ch[x][r]; ch[x][r]=y; up(y),up(x); } void Splay( int x, int &k){ while (x!=k){ int y=fa[x],z=fa[y]; if (y!=k){ if (ch[z][0]==y^ch[y][0]==x)Rotate(x,k); else Rotate(y,k); }Rotate(x,k); } }queue< int >que; int find( int x, int rnk){ down(x); if (sz[ls]+1==rnk) return x; if (sz[ls]>=rnk) return find(ls,rnk); return find(rs,rnk-sz[ls]-1); } void clean( int x){ if (!x) return ; clean(rs),clean(ls),que.push(x); fa[x]=rs=ls=tag[x]=rev[x]=0; } int Split( int k, int tot){ int x=find(rt,k),y=find(rt,k+tot+1); Splay(x,rt),Splay(y,ch[x][1]); return ch[y][0]; } void Querysum( int k, int tot){ int x=Split(k,tot); printf ( "%d\n" ,sum[x]); } void Modify( int k, int tot, int val){ int x=Split(k,tot),y=fa[x]; v[x]=val;tag[x]=1;sum[x]=sz[x]*v[x]; if (val>=0)l[x]=r[x]=Max[x]=sum[x]; else l[x]=r[x]=0,Max[x]=v[x]; up(y),up(fa[y]); } void rever( int k, int tot){ int x=Split(k,tot),y=fa[x]; if (!tag[x]){ rev[x]^=1;swap(l[x],r[x]); up(y),up(fa[y]); } } void del( int k, int tot){ int x=Split(k,tot),y=fa[x]; clean(x);ch[y][0]=0;up(y),up(fa[y]); } #define mid ((L+R)>>1) void build( int L, int R, int f){ if (L>R) return ; int x=id[mid],faa=id[f]; if (L==R){ sz[x]=1,sum[x]=a[L]; tag[x]=0; if (a[L]>=0)l[x]=r[x]=Max[x]=a[L]; else l[x]=r[x]=0,Max[x]=a[L]; } else build(L,mid-1,mid),build(mid+1,R,mid); v[x]=a[mid],fa[x]=faa;up(x); ch[faa][f<=mid]=x; } void Insert( int k, int tot){ for ( int i=1;i<=tot;++i) scanf ( "%d" ,&a[i]); for ( int i=1;i<=tot;++i) if (!que.empty())id[i]=que.front(),que.pop(); else id[i]=++cnt; build(1,tot,0); int z=id[((1+tot)>>1)]; int x=find(rt,k+1),y=find(rt,k+2); Splay(x,rt),Splay(y,ch[x][1]); fa[z]=y,ch[y][0]=z,up(y),up(x); } int k,tot; int main(){ scanf ( "%d%d" ,&n,&m);Max[0]=a[1]=a[n+2]=-6666666; for ( int i=1;i<=n;++i) scanf ( "%d" ,&a[i+1]); for ( int i=1;i<=n+2;++i)id[i]=i; build(1,n+2,0);rt=(n+3)>>1,cnt=n+2; char s[10]; for ( int i=1;i<=m;++i){ scanf ( "%s" ,s); if (s[0]== 'I' ){ scanf ( "%d%d" ,&k,&tot),Insert(k,tot);} if (s[0]== 'D' ){ scanf ( "%d%d" ,&k,&tot),del(k,tot);} if (s[0]== 'M' &&s[2]== 'K' ){ int c; scanf ( "%d%d%d" ,&k,&tot,&c),Modify(k,tot,c);} if (s[0]== 'R' ){ scanf ( "%d%d" ,&k,&tot),rever(k,tot);} if (s[0]== 'G' ){ scanf ( "%d%d" ,&k,&tot),Querysum(k,tot);} if (s[0]== 'M' &&s[2]== 'X' ){ printf ( "%d\n" ,Max[rt]);} } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步