1. 程式人生 > >【fhq Treap】bzoj1500(聽說此題多碼上幾遍就能牢記fhq Treap)

【fhq Treap】bzoj1500(聽說此題多碼上幾遍就能牢記fhq Treap)

def queue new merge gre 超過 discus make ||

1500: [NOI2005]維修數列

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 15112 Solved: 4996
[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

Sample Output

-1
10
1
10

HINT

技術分享圖片

題解

非常惡心的一道題。。。

用fhq Treap完成的話

1、把原有的平衡樹從pos處拆開,把新加的點新建一顆小平衡樹合並進去

2、把原有平衡樹從pos和pos+num處拆開,合並左右中間不要【但是記得回收下標】

3、把原有平衡樹從pos和pos+num處拆開,在中間打上標記cov

4、把原有平衡樹從pos和pos+num處拆開,在中間打上標記mark

5、把原有平衡樹從pos和pos+num處拆開,輸出sum[中間]

6、輸出ma[rt];

代碼

//by 減維
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include
<bitset> #include<algorithm> #define inf 1<<30 #define ll long long using namespace std; int n,m,rt,sz,siz[500005],son[500005][2],val[500005],lm[500005],rm[500005],ma[500005],sum[500005],mark[500005],cov[500005],pri[500005]; int a[200005]; char ch[25]; queue<int>q; int newnode(int v) { int x; if(!q.empty()) x=q.front(),q.pop(); else x=++sz; siz[x]=1; son[x][0]=son[x][1]=mark[x]=0; cov[x]=inf;pri[x]=rand(); val[x]=sum[x]=ma[x]=v; lm[x]=rm[x]=max(0,v); return x; } void upda(int x) { if(son[x][0]&&son[x][1]){ siz[x]=siz[son[x][0]]+siz[son[x][1]]+1; sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x]; ma[x]=max(max(ma[son[x][0]],ma[son[x][1]]),rm[son[x][0]]+lm[son[x][1]]+val[x]); lm[x]=max(lm[son[x][0]],sum[son[x][0]]+val[x]+lm[son[x][1]]); rm[x]=max(rm[son[x][1]],sum[son[x][1]]+val[x]+rm[son[x][0]]); }else if(son[x][0]){ siz[x]=siz[son[x][0]]+1; sum[x]=sum[son[x][0]]+val[x]; ma[x]=max(ma[son[x][0]],rm[son[x][0]]+val[x]); lm[x]=max(lm[son[x][0]],sum[son[x][0]]+val[x]); lm[x]=max(0,lm[x]); rm[x]=max(0,rm[son[x][0]]+val[x]); }else if(son[x][1]){ siz[x]=siz[son[x][1]]+1; sum[x]=sum[son[x][1]]+val[x]; ma[x]=max(ma[son[x][1]],lm[son[x][1]]+val[x]); rm[x]=max(rm[son[x][1]],sum[son[x][1]]+val[x]); rm[x]=max(0,rm[x]); lm[x]=max(0,lm[son[x][1]]+val[x]); }else{ siz[x]=1;sum[x]=ma[x]=val[x]; lm[x]=rm[x]=max(0,val[x]); } } void covered(int x,int v) { val[x]=v; sum[x]=siz[x]*v; lm[x]=rm[x]=max(0,sum[x]); ma[x]=max(sum[x],val[x]); cov[x]=v; } void zhuan(int now) { swap(son[now][0],son[now][1]); swap(lm[now],rm[now]); mark[now]^=1; } void pd(int now) { if(mark[now]){ if(son[now][0])zhuan(son[now][0]); if(son[now][1])zhuan(son[now][1]); } if(cov[now]!=inf){ if(son[now][0])covered(son[now][0],cov[now]); if(son[now][1])covered(son[now][1],cov[now]); } mark[now]=0;cov[now]=inf; } int build(int l,int r) { if(l>r)return 0; int mid=(l+r)>>1,v=a[mid]; int now=newnode(v); son[now][0]=build(l,mid-1); son[now][1]=build(mid+1,r); upda(now); return now; } void dfs(int now) { if(!now)return; dfs(son[now][0]); printf("%d ",val[now]); dfs(son[now][1]); } void spli(int now,int k,int &x,int &y) { if(!now)x=y=0; else{ pd(now); if(k<=siz[son[now][0]]) y=now,spli(son[now][0],k,x,son[now][0]); else x=now,spli(son[now][1],k-siz[son[now][0]]-1,son[now][1],y); upda(now); } } int merge(int x,int y) { if(!x||!y)return x+y; pd(x),pd(y); if(pri[x]<pri[y]) { son[x][1]=merge(son[x][1],y); upda(x); return x; }else{ son[y][0]=merge(x,son[y][0]); upda(y); return y; } } void rudui(int x) { if(!x)return ; q.push(x); rudui(son[x][0]); rudui(son[x][1]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)scanf("%d",&a[i]); rt=build(1,n); int pos,num,x,y,z,k,b,c,d; for(int i=1;i<=m;++i) { //dfs(rt);printf("\n"); scanf("%s",ch+1); if (ch[1]==I){ scanf("%d %d",&pos,&num); for(int i=1;i<=num;++i)scanf("%d",&a[i]); z=build(1,num); spli(rt,pos,x,y); rt=merge(merge(x,z),y); }else if (ch[1]==D){ scanf("%d%d",&pos,&num); spli(rt,pos-1,x,y); spli(y,num,b,c); rt=merge(x,c); rudui(b); }else if (ch[1]==M && ch[3] ==K){ scanf("%d%d%d",&pos,&num,&k); spli(rt,pos-1,x,y); spli(y,num,b,c); covered(b,k); rt=merge(x,merge(b,c)); }else if (ch[1]==R){ scanf("%d%d",&pos,&num); spli(rt,pos-1,x,y); spli(y,num,b,c); zhuan(b); rt=merge(x,merge(b,c)); }else if (ch[1]==G){ scanf("%d%d",&pos,&num); spli(rt,pos-1,x,y); spli(y,num,b,c); printf("%d\n",sum[b]); rt=merge(x,merge(b,c)); }else{ printf("%d\n",ma[rt]); } } return 0; }

【fhq Treap】bzoj1500(聽說此題多碼上幾遍就能牢記fhq Treap)