BZOJ3064 CPU监控
生活随笔
收集整理的這篇文章主要介紹了
BZOJ3064 CPU监控
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接:戳我
比較神仙的一個題(至少對于我這個小蒟蒻來說。。。)下面盡可能詳細地解釋一下吧。。。學習來源:這位神仙的題解
其實就是對于操作的轉換。我們設(x,y)為操作的參數(shù),設當前數(shù)為a,操作為max(a+x,y)——賦值即(-inf,b),增加為(a,-inf)。(是不是感覺很妙啊qwqwq)
如果標記(x2,y2)合并到(x1,y1)之后,應該是這個樣子——(x1+x2,max(y1+x2,y2))。(根據合并順序,應該不難理解)
代碼如下:
Node2 operator + (struct Node2 a,struct Node2 b){return (Node2){max(-inf,a.x+b.x),max(a.y+b.x,b.y)};} Node2 max (struct Node2 a,struct Node2 b){return (Node2){max(a.x,b.x),max(a.y,b.y)};}然后我們維護兩個標記——一個叫tag,和普通線段樹里面的lazy標記一樣,正常維護現(xiàn)在的更改。一個叫tag2,維護歷史操作。
先看核心的維護操作:
(本來solve是給push_down用的,但是其實update里面也是可以調用的。我們把a,b傳參數(shù)的時候傳一樣的即可。)
然后我們來看push_down操作:
inline void push_down(int x) {solve(ls(x),tag[x],tag2[x]);solve(rs(x),tag[x],tag2[x]);//給做右區(qū)間分別下方當前標記,和歷史標記tag[x].x=tag2[x].x=0;tag[x].y=tag2[x].y=-inf;//注意push_down之后對兩個標記的還原(因為什么都沒有加,所以x=0。//因為也不需要取最大,所以y=-inf }完整代碼如下:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define inf 0x3f3f3f3f #define MAXN 100010 using namespace std; int n,m; int a[MAXN];struct Node{int l,r,now_max,pre_max;}t[MAXN<<2];struct Node2{int x,y;}tag[MAXN<<2],tag2[MAXN<<2];Node2 operator + (struct Node2 a,struct Node2 b){return (Node2){max(-inf,a.x+b.x),max(a.y+b.x,b.y)};}Node2 max (struct Node2 a,struct Node2 b){return (Node2){max(a.x,b.x),max(a.y,b.y)};}inline int ls(int x){return x<<1;}inline int rs(int x){return x<<1|1;}inline void push_up(int x) {t[x].now_max=max(t[ls(x)].now_max,t[rs(x)].now_max);t[x].pre_max=max(t[ls(x)].pre_max,t[rs(x)].pre_max); }inline void solve(int x,Node2 a,Node2 b) {t[x].pre_max=max(t[x].pre_max,max(t[x].now_max+b.x,b.y));t[x].now_max=max(t[x].now_max+a.x,a.y);tag2[x]=max(tag2[x],tag[x]+b);tag[x]=tag[x]+a; }inline void push_down(int x) {solve(ls(x),tag[x],tag2[x]);solve(rs(x),tag[x],tag2[x]);tag[x].x=tag2[x].x=0;tag[x].y=tag2[x].y=-inf; }inline void build(int x,int l,int r) {t[x].l=l,t[x].r=r;tag[x].x=tag2[x].x=0;tag[x].y=tag2[x].y=-inf;if(l==r){t[x].now_max=t[x].pre_max=a[l];return;}int mid=(l+r)>>1;build(ls(x),l,mid);build(rs(x),mid+1,r);push_up(x); }inline void update(int x,int ll,int rr,Node2 k) {int l=t[x].l,r=t[x].r;if(ll<=l&&r<=rr){solve(x,k,k);return;}int mid=(l+r)>>1;push_down(x);if(ll<=mid) update(ls(x),ll,rr,k);if(mid<rr) update(rs(x),ll,rr,k);push_up(x); }inline int query(int x,int ll,int rr,int op) {int l=t[x].l,r=t[x].r;if(ll<=l&&r<=rr){if(op==0) return t[x].now_max;else return t[x].pre_max;}int mid=(l+r)>>1,cur_ans=-inf;push_down(x);if(ll<=mid) cur_ans=max(cur_ans,query(ls(x),ll,rr,op));if(mid<rr) cur_ans=max(cur_ans,query(rs(x),ll,rr,op));return cur_ans; }int main() {#ifndef ONLINE_JUDGEfreopen("ce.in","r",stdin);freopen("ce.out","w",stdout);#endifscanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&m);build(1,1,n);for(int i=1;i<=m;i++){char s[10];int l,r,k;Node2 cur; scanf("%s%d%d",s,&l,&r);if(s[0]=='Q') printf("%d\n",query(1,l,r,0));else if(s[0]=='A') printf("%d\n",query(1,l,r,1));else if(s[0]=='P') {scanf("%d",&k);cur.x=k,cur.y=-inf;update(1,l,r,cur);}else if(s[0]=='C'){scanf("%d",&k);cur.x=-inf,cur.y=k;update(1,l,r,cur);}}return 0; }轉載于:https://www.cnblogs.com/fengxunling/p/10508486.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的BZOJ3064 CPU监控的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android-Note
- 下一篇: 对汉诺塔递归算法的理解(图解,附完整代码