zoukankan      html  css  js  c++  java
  • CF903G Yet Another Maxflow Problem

    题目传送门

    分析:
    考虑把最大流转换成最小割来处理这个问题
    考虑这个图的特性:
    如果说我们要割去(A_i)(A_{i+1})的边,那么对于(j>i),我们就没必要割去(A_j)(A_{j+1})的边了
    (B)同理,这样(A)(B)中我们只需要至多各自割掉一条边
    因为有不割(A)(B),而多割一些中间的边代价更小的情况,由于处理起来比较麻烦,我们可以优化一下
    (A_0)(A_1)(B_n)(B_{n+1})连代价为0的边,求(A_0)(B_{n+1})的最小割
    这样(A)(B)中我们就可以各自割掉恰好一条边找到最小代价
    假设割(A_u)(A_{u+1})(B_v)(B_{v+1}),那么答案为

    (a_u+b_v+sum_{ileq u,j>v}c_{i,j})

    由于修改的只有(a_u),对于每个(v),后面的一部分的最小代价不收影响
    按顺序枚举(u),加入必须割掉的边,用线段树维护取哪个(v)代价最小,即维护全局最小值
    修改直接单点修改就好了
    复杂度(O(nlogn))

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    
    #define maxn 200005
    #define pii pair<int,int>
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m,q;
    long long A[maxn],B[maxn],C[maxn];  
    vector<pii >G[maxn];
    long long mn[maxn<<2],lz[maxn<<2];
    
    inline void build(int i,int l,int r)
    {
    	lz[i]=0;
    	if(l==r){mn[i]=B[l];return;}
    	int mid=(l+r)>>1;
    	build(i<<1,l,mid),build(i<<1|1,mid+1,r);
    	mn[i]=min(mn[i<<1],mn[i<<1|1]);
    }
    inline void pushdown(int i)
    {if(lz[i]){mn[i<<1]+=lz[i],mn[i<<1|1]+=lz[i];lz[i<<1]+=lz[i],lz[i<<1|1]+=lz[i];lz[i]=0;}}
    
    inline void update(int i,int l,int r,int ql,int qr,int w)
    {
    	if(ql>r||qr<l)return; 
    	if(ql<=l&&r<=qr){mn[i]+=w,lz[i]+=w;return;}
    	int mid=(l+r)>>1;
    	pushdown(i);
    	update(i<<1,l,mid,ql,qr,w),update(i<<1|1,mid+1,r,ql,qr,w);
    	mn[i]=min(mn[i<<1],mn[i<<1|1]);
    }
    
    int main()
    {
    	n=getint(),m=getint(),q=getint();
    	for(int i=2;i<=n;i++)A[i-1]=getint(),B[i]=getint();
    	while(m--)
    	{
    		int u=getint(),v=getint(),w=getint();
    		G[u].push_back(make_pair(v,w));
    	}
    	build(1,1,n); 
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<G[i].size();j++)update(1,1,n,1,G[i][j].first,G[i][j].second);
    		C[i]=mn[1];
    	}
    	for(int i=1;i<=n;i++)B[i]=A[i]+C[i]; 
    	build(1,1,n);
    	printf("%lld
    ",mn[1]);
    	while(q--)
    	{
    		int p=getint(),x=getint(); 
    		update(1,1,n,p,p,x-A[p]),A[p]=x; 
    		printf("%lld
    ",mn[1]);
    	}
    }
    

  • 相关阅读:
    python基础-正则2
    python基础-正则1
    python基础-私有变量和方法
    「SCOI2015」小凸玩密室 解题报告
    「JLOI2015」骗我呢 解题报告?
    「JLOI2015」城池攻占 解题报告
    【模板】左偏树(可并堆)
    网络流24题 餐巾计划问题 解题报告
    「JLOI2015」管道连接 解题报告
    [WC2008]游览计划 解题报告
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13295487.html
Copyright © 2011-2022 走看看