• CF1648D Serious Business


    场上破灭我上红的题。
    另外手速场能不能【】啊。

    题意:

    给定\(3\times n\)的矩阵,\((i,j)\)有权\(a_{i,j}\),走过的格子会强制获得其的权。
    只能走过有标记的格子,初始时,只有零二行的格子标记。
    你可以花费\(k_i\)的代价,使得第二行的\([l_i,r_i]\)被标记。
    \((1,1) \to (3,n)\),最大能获得的权(格子权和减去标记第二行所用的代价)。

    做法:

    \(f_i\)为走到\((2,i)\)停止的最大权值。

    枚举选择的最后一个操作\((l,r,k)\)

    \(f_i = \max(f_i,f_{l - 1} + suf_{2,l} - suf_{2,i + 1} - k)\)

    \(f_i = \max(f_i,pre_{1,j} + suf_{2,j} - suf_{2,i + 1} - k)(j \in [l,i])\)

    第一种直接线段树打\(tag\)即可。
    第二种即记录\(-k\)的最小值,然后遇到\([l,r]\),把\(g_i = \max g_j\ j \in [l,i - 1]\)即可,这个可以线段树上做。

    点击查看代码
    #include<bits/stdc++.h>
    #define N 500005
    #define inf 1e16
    #define ll long long 
    
    struct P{
    	ll mx1;
    	ll pmx,tag;
    }T[N * 20];
    
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    #define mid ((l + r) >> 1)
    #define mx(x) T[x].mx1
    #define pmx(x) T[x].pmx
    #define tag(x) T[x].tag
    
    ll a[4][N];
    ll pre1[N],suf2[N],suf3[N];
    
    int n,q;
    
    inline void up(int u){mx(u) = std::max(mx(ls(u)),mx(rs(u))),pmx(u) = std::max(pmx(ls(u)),pmx(rs(u)));}
    
    inline void build(int u,int l,int r){
    //	std::cout<<u<<" "<<l<<" "<<r<<"\n";
    	mx(u) = -inf,tag(u) = inf;
    	if(l == r){
    		pmx(u) = pre1[l] + suf2[l];
    		return ;
    	}
    	build(ls(u),l,mid);
    	build(rs(u),mid + 1,r);
    	up(u);
    //	std::cout<<u<<" "<<l<<" "<<r<<" "<<pmx(u)<<"\n";	
    }
    
    inline void down(int u){
    	if(tag(u) != inf){
    		mx(rs(u)) = std::max(pmx(ls(u)) - tag(u),mx(rs(u)));
    		tag(ls(u)) = std::min(tag(ls(u)),tag(u));
    		tag(rs(u)) = std::min(tag(rs(u)),tag(u));		
    //		std::cout<<"down "<<u<<" "<<mx(rs(u))<<"\n";
    	}
    }
    
    inline void change(int u,int l,int r,int tl,int tr,ll p){
    //	std::cout<<u<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<p<<std::endl; 
    	if(tl <= l && r <= tr){
    		mx(u) = std::max(mx(u),p);
    		return ;
    	}
    	down(u);
    	if(tl <= mid)
    	change(ls(u),l,mid,tl,tr,p);
    	if(tr > mid)
    	change(rs(u),mid + 1,r,tl,tr,p); 
    }
    
    inline void modify(int u,int l,int r,int tl,int tr,ll k,ll &cur){
    //	std::cout<<u<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<cur<<std::endl; 
    	if(tl <= l && r <= tr){
    		mx(u) = std::max(mx(u),cur - k);
    		tag(u) = std::min(tag(u),k);
    		cur = std::max(cur,pmx(u));
    		return ;
    	}
    	down(u);
    	if(tl <= mid)
    	modify(ls(u),l,mid,tl,tr,k,cur);
    	if(tr > mid)
    	modify(rs(u),mid + 1,r,tl,tr,k,cur);	
    }
    
    inline ll find(int u,int l,int r,int p){
    //	std::cout<<"FIND "<<u<<" "<<l<<" "<<r<<" "<<p<<std::endl; 	
    	if(l == r){
    		return std::max(mx(u),pmx(u) - tag(u));
    	}
    	ll res = mx(u);
    	down(u);
    	if(p <= mid)
    	res = std::max(res,find(ls(u),l,mid,p));
    	if(p > mid)
    	res = std::max(res,find(rs(u),mid + 1,r,p));
    	return res;
    }
    
    using std::vector;
    using std::pair;
    
    #define pii pair<int,int>
    #define mp std::make_pair 
    
    ll f[N];
    
    vector<pii>G[N];
    
    ll ans = -inf;
    
    int main(){
    //	freopen("table1.out","w",stdout);
    	scanf("%d%d",&n,&q);
    	for(int i = 1;i <= n;++i)
    	scanf("%lld",&a[1][i]),pre1[i] = pre1[i - 1] + a[1][i];
    	for(int i = 1;i <= n;++i)
    	scanf("%lld",&a[2][i]);
    	for(int i = n;i >= 1;--i)
    	suf2[i] = suf2[i + 1] + a[2][i];
    	for(int i = 1;i <= n;++i)
    	scanf("%lld",&a[3][i]);
    	for(int i = n;i >= 1;--i)
    	suf3[i] = suf3[i + 1] + a[3][i];
    	build(1,1,n);
    	while(q -- ){
    		int l,r,k;
    		scanf("%d%d%d",&l,&r,&k);
    		G[l].push_back(mp(r,k)); 
    	}	
    	int now = 0;
    	f[0] = -inf;
    	for(int i = 1;i <= n;++i){
    		while(now + 1 < i) now ++ , f[now] = find(1 , 1 , n , now) , f[now] -= suf2[now + 1] , ans = std::max(ans , f[now] + suf3[now]);
    		for(auto it : G[i]){
    			int r = it.first,k = it.second;
    //			std::cout<<i<<" "<<r<<" "<<k<<std::endl;
    			change(1,1,n,i,r,f[i - 1] + suf2[i] - k);
    			ll cur = -inf;
    			modify(1,1,n,i,r,k,cur);
    		}
    	}
    	while(now + 1 <= n) now ++ , f[now] = find(1 , 1 , n , now) , f[now] -= suf2[now + 1] , ans = std::max(ans , f[now] + suf3[now]);	
    //	for(int i = 1;i <= n;++i)
    //	std::cout<<f[i]<<" ";
    //	puts("");
    	std::cout<<ans<<"\n";
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    致亲爱的304
    C语言中简单的for循环和浮点型变量
    C程序内存管理
    变量
    我哭了
    那一场邂逅
    如何修改安卓项目的图标
    Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead.解决方法
    Android 异步加载
    大家好,第一次用博客记录一些东西
  • 原文地址:https://www.cnblogs.com/dixiao/p/15975357.html
Copyright © 2020-2023  润新知