1. 程式人生 > >BZOJ3064: Tyvj 1518 CPU監控

BZOJ3064: Tyvj 1518 CPU監控

ide 發現 open d+ += display max log mage

n<=100000的數列支持以下操作:一、區間加;二、區間賦值;三、查區間最大;四、查區間歷史版本最大。

惡心死我了。。可能很水,但我調了半天。

錯誤!調了兩天。

這裏有一個棘手問題:歷史版本。

首先不看賦值操作。記倆標記——區間加add和區間歷史加標記pre。其中後者的含義是“從上一次這個區間標記下傳到現在,區間加(前者)標記的最大值”。這樣,比如某點i的標記下傳給兒子x,標記如此疊加:$pre_x>?=pre_i+add_x$,$add_x+=add_i$,同時更新區間歷史版本最大值:$his_x>?=Max_x+pre_x-add_x$。

然後加入賦值操作。可以發現一個區間在標記下傳前只有兩個階段:一開始只有加標記,後來只有賦值標記:打上賦值標記後,如果該區間還要加,相當於更新賦值標記。因此,分兩種歷史標記來搞,一個記第一階段的$add$的最大值,一個記第二階段$be$的最大值。下傳時註意順序。

關鍵點截圖留念:

技術分享圖片

技術分享圖片

技術分享圖片
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<math.h>
  6 //#include<complex>
  7 //#include<ctime>
  8 #include<algorithm>
  9 using namespace std;
 10 
 11 int n,m;
 12 #define maxn 100011
 13
const int inf=0x3f3f3f3f; 14 int num[maxn]; 15 struct SMT 16 { 17 struct Node 18 { 19 int ls,rs; 20 int add,pa,be,pb; 21 int Max,pmax; 22 }a[maxn<<1]; 23 int size,root; 24 SMT() {size=root=0; a[0].Max=a[0].pmax=-inf;} 25 void up(int x,int
L,int R) 26 { 27 int &p=a[x].ls,&q=a[x].rs; 28 a[x].Max=max(a[p].Max,a[q].Max); 29 a[x].pmax=max(a[p].pmax,a[q].pmax); 30 } 31 void addsingle(int x,int L,int R,int v,int pv) 32 { 33 if (a[x].be!=-inf) 34 {besingle(x,L,R,a[x].be+v,a[x].be+pv); return;} 35 a[x].pa=max(a[x].pa,a[x].add+pv),a[x].add+=v; 36 a[x].Max+=v; a[x].pmax=max(a[x].pmax,a[x].pa+a[x].Max-a[x].add); 37 } 38 void besingle(int x,int L,int R,int v,int pv) 39 { 40 a[x].pb=max(a[x].pb,pv); a[x].add=0; a[x].be=v; 41 a[x].Max=v; a[x].pmax=max(a[x].pmax,a[x].pb); 42 } 43 void down(int x,int L,int R) 44 { 45 int &p=a[x].ls,&q=a[x].rs,mid=(L+R)>>1; 46 if (a[x].add || a[x].pa) 47 addsingle(p,L,mid,a[x].add,a[x].pa),addsingle(q,mid+1,R,a[x].add,a[x].pa),a[x].add=a[x].pa=0; 48 if (a[x].be!=-inf || a[x].pb!=-inf) 49 besingle(p,L,mid,a[x].be,a[x].pb),besingle(q,mid+1,R,a[x].be,a[x].pb),a[x].be=a[x].pb=-inf; 50 } 51 void build(int &x,int L,int R) 52 { 53 x=++size; 54 a[x].add=a[x].pa=0; a[x].be=a[x].pb=-inf; 55 if (L==R) {a[x].ls=a[x].rs=0; a[x].Max=a[x].pmax=num[L];return;} 56 int mid=(L+R)>>1; 57 build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x,L,R); 58 } 59 void build() {build(root,1,n);} 60 int ql,qr,v; 61 void Add(int &x,int L,int R) 62 { 63 if (ql<=L && R<=qr) {addsingle(x,L,R,v,v); return;} 64 down(x,L,R); 65 int mid=(L+R)>>1; 66 if (ql<=mid) Add(a[x].ls,L,mid); 67 if (qr> mid) Add(a[x].rs,mid+1,R); 68 up(x,L,R); 69 } 70 void add(int L,int R,int v) 71 { 72 ql=L; qr=R; this->v=v; 73 Add(root,1,n); 74 } 75 void Be(int &x,int L,int R) 76 { 77 if (ql<=L && R<=qr) {besingle(x,L,R,v,v); return;} 78 down(x,L,R); 79 int mid=(L+R)>>1; 80 if (ql<=mid) Be(a[x].ls,L,mid); 81 if (qr> mid) Be(a[x].rs,mid+1,R); 82 up(x,L,R); 83 } 84 void be(int L,int R,int v) 85 { 86 ql=L; qr=R; this->v=v; 87 Be(root,1,n); 88 } 89 int Qmax(int &x,int L,int R) 90 { 91 if (ql<=L && R<=qr) return a[x].Max; 92 down(x,L,R); 93 int mid=(L+R)>>1,ans=-inf; 94 if (ql<=mid) ans=Qmax(a[x].ls,L,mid); 95 if (qr> mid) ans=max(ans,Qmax(a[x].rs,mid+1,R)); 96 return ans; 97 } 98 int qmax(int L,int R) 99 { 100 ql=L; qr=R; 101 return Qmax(root,1,n); 102 } 103 int Qpmax(int &x,int L,int R) 104 { 105 if (ql<=L && R<=qr) return a[x].pmax; 106 down(x,L,R); 107 int mid=(L+R)>>1,ans=-inf; 108 if (ql<=mid) ans=Qpmax(a[x].ls,L,mid); 109 if (qr> mid) ans=max(ans,Qpmax(a[x].rs,mid+1,R)); 110 return ans; 111 } 112 int qpmax(int L,int R) 113 { 114 ql=L; qr=R; 115 return Qpmax(root,1,n); 116 } 117 }t; 118 119 int main() 120 { 121 scanf("%d",&n); 122 for (int i=1;i<=n;i++) scanf("%d",&num[i]); 123 t.build(); 124 125 scanf("%d",&m); 126 int x,y,z; char id; 127 while (m--) 128 { 129 while ((id=getchar())<A || id>Z); 130 if (id==A) scanf("%d%d",&x,&y),printf("%d\n",t.qpmax(x,y)); 131 else if (id==Q) scanf("%d%d",&x,&y),printf("%d\n",t.qmax(x,y)); 132 else if (id==P) scanf("%d%d%d",&x,&y,&z),t.add(x,y,z); 133 else scanf("%d%d%d",&x,&y,&z),t.be(x,y,z); 134 } 135 return 0; 136 }
View Code

BZOJ3064: Tyvj 1518 CPU監控