【題解】CPU監控

CPU監控

\(\text{Solution:}\)

觀察到有區間加以及區間覆蓋,而詢問歷史最大值是一個相對棘手的問題。

觀察到沒有區間最值操作。考慮按照時間軸來下傳標記:記錄 \(cov[0],ad[0]\) 表示當前的覆蓋、加法標記,\(cov[1],ad[1]\) 表示自從上次下傳標記以來到現在的最大加法標記、最大覆蓋標記。

考慮標記下傳的問題。在 pushdown 中毫無疑問是加法先下傳,問題在於更改的時候如何具體把值下傳過去?

考慮線段樹的執行過程,發現性質。首先,一個點的父節點的未更新時間必定與它沒有交集並且靠後

在這樣的情況下標記下傳纔有了正確性:

在加法的下傳中:

如果沒有被覆蓋,那麼我們應當用 \(ad[0]+now\) 來更新 \(ad[1],\)\(maxn[0]+ad[1]\) 來更新 \(maxn[1]\) (注意這裏是更新後的 \(ad[1]\)) 接着就是 ad[0]+=now,maxn[0]+=now

如果被覆蓋了,我們就直接考慮修改覆蓋標記,調用 update(cov[0]+now,cov[1]+now,x,1) 來更新覆蓋標記。

接下來考慮如何更新覆蓋標記:

如果沒有被覆蓋,我們直接令 \(cov[1]=now,\) 並且使得標記覆蓋的值爲 true

否則,直接取一個 \(\max\) 即可。

其他信息:maxn[1]=Max(maxn[1],now),maxn[0]=cov[0]=now,ad[0]=0

如上所述就完成了修改。其他的就是注意不要忘記 pushdown,pushup 了。

時間複雜度是一個 $\log $ 的。

#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
#define Bt(a) bitset<a>
#define bc __builtin_popcount
#define pc putchar
#define ci const int&
const int mod = 1e9 + 7;
const db eps = 1e-10;
const int inf = (1 << 30);
inline int Max(ci x, ci y) {return x > y ? x : y;}
inline int Min(ci x, ci y) {return x < y ? x : y;}
inline db Max(db x, db y) {return x - y > eps ? x : y;}
inline db Min(db x, db y) {return x - y < eps ? x : y;}
inline int Add(ci x, ci y, ci M = mod) {return (x + y) % M;}
inline int Mul(ci x, ci y, ci M = mod) {return 1ll * x * y % M;}
inline int Dec(ci x, ci y, ci M = mod) {return (x - y + M) % M;}
typedef pair<int, int> pii;
inline int Abs(int x) {return x < 0 ? -x : x;}
//char buf[1<<21],*p1=buf,*p2=buf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char Obuf[105000],*O=Obuf;//Siz shoule be the size of Out File
int pst[30],ptop;
inline void Fprint(){fwrite(Obuf,1,O-Obuf,stdout);}
inline void Fwrite(int x){
  if(x==0){*O++='0';return;}
  if(x<0)*O++='-',x=-x;ptop=0;
  while(x)pst[++ptop]=x%10,x/=10;
  while(ptop)*O++=pst[ptop--]+'0';
  if(O-Obuf>100000)Fprint(),O=Obuf;
}
inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') w = -1;ch = getchar();}
    while (isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
    return s * w;
}
inline void write(int x) {
    if (x < 0)putchar('-'), x = -x;
    if (x > 9)write(x / 10);
	pc(x % 10 + '0');
}
inline int qpow(int x, int y) {
    int res = 1;
    while (y) {if (y & 1)res = Mul(res, x);x = Mul(x, x);y >>= 1;}
    return res;
}
inline void cadd(int &x, int y) {x += y;}
inline void cmul(int &x, int y) {x *= y;}
inline void cmax(int &x, int y) {x = Max(x, y);}
inline void cmin(int &x, int y) {x = Min(x, y);}
const int N=2e6+10;
namespace Refined_heart{
	int n,m;
	namespace SGT{
		struct TREE{
			int l,r,maxn[2],cov[2],ad[2],isc;
//			inline void print(){
//				printf("%d %d %d %d %d %d %d %d\n",l,r,maxn[0],maxn[1],cov[0],cov[1],ad[0],ad[1]);
//			}
		}tr[N];
		#define ls (x<<1)
		#define rs (x<<1|1)
		inline void pushup(int x){
			tr[x].maxn[0]=Max(tr[ls].maxn[0],tr[rs].maxn[0]);
			tr[x].maxn[1]=Max(tr[ls].maxn[1],tr[rs].maxn[1]);
		}
		void build(int l,int r,int x){
			tr[x].l=l;tr[x].r=r;
			tr[x].cov[0]=tr[x].cov[1]=-inf;
			tr[x].ad[0]=tr[x].ad[1]=0;
			tr[x].maxn[0]=tr[x].maxn[1]=-inf;
			if(l==r){
				tr[x].maxn[0]=tr[x].maxn[1]=read();
				return;
			}
			int mid=(l+r)>>1;
			build(l,mid,ls);build(mid+1,r,rs);
			pushup(x);
		}
		inline void update(int v0,int v1,int x,int op){
			if(op==0){
				if(tr[x].isc)update(tr[x].cov[0]+v0,tr[x].cov[0]+v1,x,1);
				else {
					tr[x].ad[1]=Max(tr[x].ad[1],tr[x].ad[0]+v1);
					tr[x].ad[0]+=v0;
					tr[x].maxn[1]=Max(tr[x].maxn[1],tr[x].maxn[0]+v1);
					tr[x].maxn[0]+=v0;
				}
				return;
			}
			if(tr[x].isc){
				tr[x].cov[1]=Max(tr[x].cov[1],v1);
			}
			else {
				tr[x].isc=1;
				tr[x].cov[1]=v1;
			}
			tr[x].maxn[1]=Max(tr[x].maxn[1],v1);
			tr[x].cov[0]=tr[x].maxn[0]=v0;
			tr[x].ad[0]=0;
		}
		inline void pushdown(int x){
			if(tr[x].ad[0]!=0||tr[x].ad[1]!=0){
				int &v0=tr[x].ad[0];
				int &v1=tr[x].ad[1];
				update(v0,v1,ls,0);
				update(v0,v1,rs,0);
				v0=v1=0;
			}
			if(tr[x].cov[0]!=-inf){
				int &v0=tr[x].cov[0];
				int &v1=tr[x].cov[1];
				update(v0,v1,ls,1);
				update(v0,v1,rs,1);
				v0=v1=-inf;tr[x].isc=0;
			}
		}
		void change_A(int x,int l,int r,int c){
			if(tr[x].l>r||tr[x].r<l)return;
			if(tr[x].l>=l&&tr[x].r<=r){
				update(c,c,x,0);
				return;
			}
			pushdown(x);change_A(ls,l,r,c);change_A(rs,l,r,c);
			pushup(x);
		}
		void change_C(int x,int l,int r,int c){
			if(tr[x].l>r||tr[x].r<l)return;
			if(tr[x].l>=l&&tr[x].r<=r){
				update(c,c,x,1);
				return;
			}
			pushdown(x);
			change_C(ls,l,r,c);change_C(rs,l,r,c);
			pushup(x);
		}
		int query_Q(int x,int l,int r){
			if(tr[x].l>r||tr[x].r<l)return -inf;
			if(tr[x].l>=l&&tr[x].r<=r)return tr[x].maxn[0];
			pushdown(x);return Max(query_Q(ls,l,r),query_Q(rs,l,r));
		}
		int query_A(int x,int l,int r){
			if(tr[x].l>r||tr[x].r<l)return -inf;
			if(tr[x].l>=l&&tr[x].r<=r)return tr[x].maxn[1];
			pushdown(x);return Max(query_A(ls,l,r),query_A(rs,l,r));
		}
	} 
	using namespace SGT;
	void solve(){
		n=read();SGT::build(1,n,1);
		m=read();
		while(m--){
			char opt[3];
			scanf("%s",opt);
			int ans=-inf;
			if(opt[0]=='Q'){
				int l=read(),r=read();
				ans=query_Q(1,l,r);
			}
			if(opt[0]=='A'){
				int l=read(),r=read();
				ans=query_A(1,l,r);
			}
			if(opt[0]=='P'){
				int l=read(),r=read(),c=read();
				change_A(1,l,r,c);
			}
			if(opt[0]=='C'){
				int l=read(),r=read(),c=read();
				change_C(1,l,r,c);
			}
			if(ans!=-inf){
				write(ans);
				pc('\n');
			}
		}
	}
}
signed main(){
	freopen("in.txt","r",stdin);
	freopen("My.out","w",stdout);
	Refined_heart::solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章