zoukankan      html  css  js  c++  java
  • CodeForces

    Codeforces - 434D

    题目大意:

    给定一个长为n的序列,序列中的第i为上的值(x_i),序列第i位上的值(x_iin[l_i,r_i]),价值为(f_i(x_i)),其中(f_i(x) = a_ix^2 + b_ix + c_i),同时给出m个限制条件,每个限制条件用一个三元组(<u,v,d>)来表示,需要序列满足(x_u leq x_v + d)。求在满足所限制条件的情况下的(f_i(x_i))的最大和。
    其中满足((1 leq n leq 50, 0 leq m leq 100 , -100 leq l_i leq r_i leq 100))

    题目解答:

    这道题跟[bzoj 3144 切糕]类似,由于网上关于切糕的题解已经烂大街了,在这里就不说了.
    首先我们考虑在没有(x_i)的限制之下的答案计算:
    直接取每段内的(max)不就好了嘛... ...

    开一开脑洞,你就会构造出一个跟切糕差不多的层次模型

    这不过这次是"最大割"而已

    我们可以把所有有价值的边权全部都被所有值中的最大值减一下

    这样我们直接求最小流再调整就行了。

    而对于(X_u <= X_v + d)的限制

    我们直接应用和切糕一样的思想来限制就可以了

    一遍最大流即可

    (ans = (max(f_i(x)) + 1)*n - maxflow)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
    inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
    const int maxn = 51;
    const int maxm = 128;
    const int maxnode = 25400;
    const int maxedge = 254000;
    const int inf = 0x3f3f3f3f;
    struct Edge{
    	int to,next,cap;
    }G[maxedge];
    int head[maxnode],cnt=1;
    void add(int u,int v,int c){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	G[cnt].cap = c;
    	head[u] = cnt;
    }
    inline void insert(int u,int v,int c){
    	add(u,v,c);add(v,u,0);
    }
    int dis[maxnode],q[maxnode],l,r;
    int S,T;
    #define v G[i].to
    bool bfs(){
    	memset(dis,-1,sizeof dis);
    	dis[S] = 0;l = 0;r = -1;
    	q[++r] = S;
    	while(l <= r){
    		int u = q[l++];
    		for(int i = head[u];i;i=G[i].next){
    			if(dis[v] == -1 && G[i].cap){
    				dis[v] = dis[u] + 1;
    				q[++r] = v;
    			}
    		}
    	}return dis[T] != -1;
    }int cur[maxnode];
    int dfs(int u,int f){
    	if(u == T || f == 0) return f;
    	int ret = 0;
    	for(int &i = cur[u];i;i=G[i].next){
    		if(dis[v] == dis[u] + 1 && G[i].cap){
    			int x = dfs(v,cat_min(G[i].cap,f));
    			ret += x;f -= x;
    			G[i].cap -= x;G[i^1].cap += x;
    			if(f == 0) break;
    		}
    	}if(ret == 0) dis[u] = -1;
    	return ret;
    }
    inline int dinic(){
    	int ret = 0;
    	while(bfs()){
    		memcpy(cur,head,sizeof head);
    		ret += dfs(S,inf);
    	}return ret;
    }
    #undef v
    int n;
    inline int f(int x,int y){
    	y += 102;
    	return x*210+y;
    }
    int a[maxn],b[maxn],c[maxn],le[maxn],ri[maxn];
    inline int calc(int i,int x){
    	return a[i]*x*x+b[i]*x+c[i];
    }
    int main(){
    	S = maxnode - 5;T = S+1;
    	read(n);int m;read(m);
    	int lim = -inf;
    	for(int i=1;i<=n;++i){
    		read(a[i]);read(b[i]);read(c[i]);
    	}
    	for(int i=1;i<=n;++i){
    		read(le[i]);read(ri[i]);
    		insert(S,f(i,le[i]-1),inf);
    		for(int j=le[i];j<=ri[i];++j){
    			lim = cat_max(lim,calc(i,j)+1);	
    		}
    		insert(f(i,ri[i]),T,inf);
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=le[i];j<=ri[i];++j){
    			insert(f(i,j-1),f(i,j),lim - calc(i,j));
    		}
    	}
    	for(int i=1,u,v,d;i<=m;++i){
    		read(u);read(v);read(d);
    		for(int j=le[u];j<=ri[u];++j){
    			if(j - d - 1 >= le[v] - 1 && j - d -1 <= ri[v])
    				insert(f(u,j-1),f(v,j-d-1),inf);
    		}
    	}
    	int ans = dinic();
    	printf("%d
    ",lim*n - ans);
    	getchar();getchar();
    	return 0;
    }
      
    
  • 相关阅读:
    四则运算2实验及表格
    四则运算2初步构思
    2015.3.6的程序实践
    对《梦断代码》的阅读计划
    林锐——软件思想阅读笔记2
    二维数组最大子数组溢出问题
    循环数组求最大子数组
    电梯调度需求分析调研报告
    二维数组求最大子数组
    四则运算实现用户输入答案并统计正确数量
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6337959.html
Copyright © 2011-2022 走看看