【题解】 CF115E:Linear Kingdom Races

Linear Kingdom Races

如果考虑每个比赛是否进行,有些比赛会有道路会重叠,代价会重复计算,所以设状态为 \(f_i\) 为在前 \(i\) 个道路中选了若干个道路获得最大利润。

选择不修这个道路,那直接转移 \(f_i=f_{i-1}\)

选择修这个道路,选择一个枚举点 \(j\)\(f_i=max\{{ f_j+val(j+1,i)-cost(j+1,i)}\}\)\(val(j+1,i)\)表示区间 \([j+1,i]\) 所有比赛的总获利,\(cost(j+1,i)\) 表示修区间 \([j+1,i]\) 全部的道路所用的代价。

发现求最大值可以用线段树维护 \(t[x]\) 使得选出最大的值转移。

对于新的i:

\([0,i-1]\)\(t[x]\) 都减去 \(a_i\) 因为都需要修这条道路。

对于当前 \(r=i\) 的比赛(\(l,r,w\)),\([0,l-1]\)\(t[x]\) 都会获得该利润,都加上 \(w\)

\([0,i-1]\)\(t[x]\) 最大值转移到 \(t[i]\)

我觉得这就是所谓的被动转移吧,我们主动选择比赛进行转移就是所谓的主动转移,我们维护最大值转移就是所谓的被动转移。

#include <bits/stdc++.h>
#define ll long long
#define int ll
#define ls p<<1
#define rs p<<1|1 
#define re register 
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
#define lb(x) x&(-x); 
using namespace std;
const int N=1e6+10;
const int B=1e6+5;
const int M=8e6+10;
const int mod=1e9+7;

int n,m;
int a[N];
int f[N];
vector<pir> v[N];

int t[N];
int maxn[N<<2];
int tag[N<<2];

void pushdown(int p){
	if(!tag[p]) return;
	maxn[ls]+=tag[p];
	maxn[rs]+=tag[p];
	tag[ls]+=tag[p];
	tag[rs]+=tag[p];
	tag[p]=0;
}

void change(int p,int pl,int pr,int l,int r,int w){
	if(l<=pl&&pr<=r){
		maxn[p]+=w;
		tag[p]+=w;
		return;
	}
	pushdown(p);
	int mid=(pl+pr)>>1;
	if(l<=mid) change(ls,pl,mid,l,r,w);
	if(r>mid) change(rs,mid+1,pr,l,r,w);
	maxn[p]=max(maxn[ls],maxn[rs]);
	return;
}

int query(int p,int pl,int pr,int l,int r){
	if(l<=pl&&pr<=r){
		return maxn[p];
	}
	pushdown(p);
	int mid=(pl+pr)>>1;
	int res=-1e9;
	if(l<=mid) res=max(res,query(ls,pl,mid,l,r));
	if(r>mid) res=max(res,query(rs,mid+1,pr,l,r));
	return res;
}

void solve(){
	// freopen("a.in","r",stdin);
	// freopen("a.out","w",stdout);  
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=m;i++){
		int l,r,w;
		cin>>l>>r>>w;
		v[r].push_back({l,w});
	}
	for(int i=1;i<=n;i++){
		change(1,0,n,0,i-1,-a[i]);
		for(auto j:v[i]){
			change(1,0,n,0,j.first-1,j.second);
		}
		f[i]=max(f[i-1],query(1,0,n,0,i-1));
		change(1,0,n,i,i,f[i]);
	}
	cout<<f[n]<<"\n";
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(nullptr);   
	int t=1;
	// cin>>t;
	while(t--){
		solve();
	}
    return 0;
}
posted @ 2025-01-25 15:26  sad_lin  阅读(14)  评论(0)    收藏  举报