吉司機大雜燴

wuhupai發表於2024-03-31

CPU監控

歷史最大值可以讓我們想到吉司機,然後發現這裡有個就要考慮區間推平和區間加對lazytag的影響。我們要維護6個tag,maxx,hmaxx,ha,a,hc,c。考慮之前的線段樹對於區間覆蓋和區間加之怎麼做的。我們發現如果我們有一個c標記,那麼如果我們要下傳一個ad標記,那麼我們可以讓c加上ad。如果我們要下傳一個c標記那我們就覆蓋c標記。考慮推廣到吉司機上。發現有四種情況(視作一開始就有ad標記,且值為0,所以不會有沒ad的情況)

重點程式碼:

void push_up(long long p){
	d[p].maxx=max(d[p<<1].maxx,d[p<<1|1].maxx);
	d[p].hmaxx=max(d[p<<1].hmaxx,d[p<<1|1].hmaxx);
}
void update(long long ad,long long had,long long c,long long hc,long long p){
	if(d[p].c!=-1e16){
		d[p].hc=max(d[p].hc,d[p].c+had);
		d[p].c+=ad;
	}else{
		d[p].had=max(d[p].had,d[p].ad+had);
		d[p].ad+=ad;
	}
	d[p].hmaxx=max(d[p].hmaxx,d[p].maxx+had);
	d[p].maxx+=ad;
	if(c!=-1e16){
		if(d[p].c!=-1e16){
			d[p].hc=max(d[p].hc,hc);
			d[p].c=c;
		}else{
			d[p].hc=hc;
			d[p].c=c;
		}
		d[p].maxx=c;
		d[p].hmaxx=max(d[p].hmaxx,hc);
	}
}
void push_down(long long p){
	update(d[p].ad,d[p].had,d[p].c,d[p].hc,p<<1);
	update(d[p].ad,d[p].had,d[p].c,d[p].hc,p<<1|1);
	d[p].c=d[p].hc=-1e16;
	d[p].ad=d[p].had=0;
}
void update_ad(long long l,long long r,long long p,long long s,long long t,long long ad){
	if(l>=s&&r<=t){
		if(d[p].c!=-1e16){
			d[p].hc=max(d[p].hc,d[p].c+ad);
			d[p].c+=ad;
		}else{
			d[p].had=max(d[p].had,d[p].ad+ad);
			d[p].ad+=ad;
		}
		d[p].hmaxx=max(d[p].hmaxx,d[p].maxx+ad);
		d[p].maxx+=ad;
		return;
	}
	long long mid=(l+r)>>1;
	push_down(p);
	if(s<=mid) update_ad(l,mid,p<<1,s,t,ad);
	if(t>mid) update_ad(mid+1,r,p<<1|1,s,t,ad);
	push_up(p);
}
void update_c(long long l,long long r,long long p,long long s,long long t,long long c){
	if(l>=s&&r<=t){
		if(d[p].c!=-1e16){
			d[p].hc=max(d[p].hc,c);
			d[p].c=c;
		}else{
			d[p].hc=c;
			d[p].c=c;
		}
		d[p].maxx=c;
		d[p].hmaxx=max(d[p].hmaxx,c);
		return;
	}
	long long mid=(l+r)>>1;
	push_down(p);
	if(s<=mid) update_c(l,mid,p<<1,s,t,c);
	if(t>mid) update_c(mid+1,r,p<<1|1,s,t,c);
	push_up(p);
}

線段樹 3
沒有2的操作上面講過了,然後考慮區間推平怎麼做。我們可以維護一個maxx,se,mx_ad,ad,cnt然後還有普通的sum,hmx_ad,had,hmaxx然後區間推平時如果這個區間只有一種數大於推平的數,那麼就操作,否則就遞迴下去。因為這個只有ad標記,上面都講過了

void push_up(long long p){//好理解
	d[p].sum=d[p<<1].sum+d[p<<1|1].sum;
	d[p].maxx=max(d[p<<1].maxx,d[p<<1|1].maxx);
	d[p].hmaxx=max(d[p<<1].hmaxx,d[p<<1|1].hmaxx);
	if(d[p<<1].maxx==d[p<<1|1].maxx){
		d[p].se=max(d[p<<1].se,d[p<<1|1].se);
		d[p].cnt=d[p<<1].cnt+d[p<<1|1].cnt;
	}else if(d[p<<1].maxx>d[p<<1|1].maxx){
		d[p].se=max(d[p<<1|1].maxx,d[p<<1].se);
		d[p].cnt=d[p<<1].cnt;
	}else if(d[p<<1].maxx<d[p<<1|1].maxx){
		d[p].se=max(d[p<<1].maxx,d[p<<1|1].se);
		d[p].cnt=d[p<<1|1].cnt;
	}
}
void update(long long mx_ad,long long mx_had,long long ad,long long had,long long p){//順序,se的id(好理解)
	d[p].sum+=(ad*(d[p].r-d[p].l+1-d[p].cnt)+mx_ad*d[p].cnt);
	d[p].hmaxx=max(d[p].maxx+mx_had,d[p].hmaxx);
	d[p].maxx+=mx_ad;
	if(d[p].se!=1e16) d[p].se+=ad;
	d[p].mx_had=max(d[p].mx_had,mx_had+d[p].mx_ad);
	d[p].had=max(d[p].had,had+d[p].ad);
	d[p].ad+=ad;
	d[p].mx_ad+=mx_ad;
}
void push_down(long long p){
	int maxx=max(d[p<<1].maxx,d[p<<1|1].maxx);//這裡要臨時存一下,不然會變
	if(maxx==d[p<<1].maxx) update(d[p].mx_ad,d[p].mx_had,d[p].ad,d[p].had,p<<1);//下傳的是對應的la,是maxx傳maxx,否則傳次大值的
	else update(d[p].ad,d[p].had,d[p].ad,d[p].had,p<<1);
	if(maxx==d[p<<1|1].maxx) update(d[p].mx_ad,d[p].mx_had,d[p].ad,d[p].had,p<<1|1);
	else update(d[p].ad,d[p].had,d[p].ad,d[p].had,p<<1|1);
	d[p].mx_had=d[p].mx_ad=d[p].had=d[p].ad=0;
}
void update_ad(long long l,long long r,long long p,long long s,long long t,long long ad){
	if(l>=s&&r<=t){
		d[p].sum+=ad*(d[p].r-d[p].l+1);
		d[p].hmaxx=max(d[p].maxx+ad,d[p].hmaxx);
		d[p].maxx+=ad;
		if(d[p].se!=1e16) d[p].se+=ad;
		d[p].mx_had=max(d[p].mx_had,d[p].mx_ad+ad);
		d[p].had=max(d[p].had,d[p].ad+ad);
		d[p].ad+=ad;
		d[p].mx_ad+=ad;
		return;
	}
	long long mid=(l+r)>>1;
	push_down(p);
	if(s<=mid) update_ad(l,mid,p<<1,s,t,ad);
	if(t>mid) update_ad(mid+1,r,p<<1|1,s,t,ad);
	push_up(p);
}
void update_min(long long l,long long r,long long p,long long s,long long t,long long ad){
	if(ad>=d[p].maxx) return;
	if(l>=s&&r<=t&&ad>d[p].se){
		d[p].sum-=d[p].cnt*(d[p].maxx-ad);
		d[p].mx_ad-=(d[p].maxx-ad);
		d[p].maxx=ad;
		return;
	}
	long long mid=(l+r)>>1;
	push_down(p);
	if(s<=mid) update_min(l,mid,p<<1,s,t,ad);
	if(t>mid) update_min(mid+1,r,p<<1|1,s,t,ad);
	push_up(p);
}

相關文章