zoukankan      html  css  js  c++  java
  • POJ2750 Potted Flower (线段树+动态规划)

    题目链接:传送门
     
    题意:题目的意思是说在一个环形的盆中选取连续的子区间使得价值/吸引力最大,然后我们有一种操作即将花盆A的吸引力替换为B(单点修改),然后每次修改输出吸引力的最大价值

    解题思路:把环从一个地方切断,使得环称为一条直线,用线段树记录当前区间的非空最大子列和非空最小子列,如果换上的数都是正数那么直接输出环的总价值-最小价值的盆,否则,输出(Max(根节点的非空子列的总价值,环的总价值-根节点的非空最小价值的子列))
    我们需要存储一下信息
    ps:结点[a,m],[m+1,b]分别是root的左右儿子区间
    Maxkey[N<<2],minkey[N<<2]//分别表示最大连续子列的价值和
    lmax[N<<2],rmax[N<<2]//分别表示结点[a,b]包含a的最大连续子列价值和,结点[a,b]包含b的最大连续子列价值和
    lmin[N<<2],rmin[N<<2]//分别表示结点[a,b]包含a的最小连续子列价值和,结点[a,b]包含b的最小连续子列价值和
    sum[N<<2]//结点[a,b]的价值和
    我们设父亲结点为k,左右子节点分别为l,r我们可以得出状态转移方程:
    (maxkey[k] = max(max(maxkey[l],maxkey[r]),rmax[l] + lmax[r]))
    (minkey[k] = min(min(minkey[l],minkey[r]),rmin[l] + lmin[r]))
    (lmax[k] = max(lmax[l],sum[l]+lmax[r]))
    (rmax[k] = max(rmax[r],sum[r]+rmax[l]))
    (lmin[k] = min(lmin[l],sum[l]+lmin[r]))
    (rmin[k] = min(rmin[r],sum[r]+rmin[l]))
     
    Code:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    typedef long long ll;
    const int INF = 0x3f3f3f3f3f;
    const int N = 100005;
    int a[N],tree[N],lazy[N];
    int sum[N<<2],maxkey[N<<2],minkey[N<<2];
    int lmax[N<<2],rmax[N<<2];
    int lmin[N<<2],rmin[N<<2];
    
    void pushup(int k) {
    	int l = k << 1;
    	int r = k << 1 | 1;
    	sum[k] = sum[l] + sum[r];
    	maxkey[k] = max(max(maxkey[l],maxkey[r]),rmax[l] + lmax[r]);
    	minkey[k] = min(min(minkey[l],minkey[r]),rmin[l] + lmin[r]);
    	lmax[k] = max(lmax[l],sum[l]+lmax[r]);
    	rmax[k] = max(rmax[r],sum[r]+rmax[l]);
    	lmin[k] = min(lmin[l],sum[l]+lmin[r]);
    	rmin[k] = min(rmin[r],sum[r]+rmin[l]);
    }
    
    void build(int l,int r,int k) {
    	if(l == r) {
    		maxkey[k] = minkey[k] = lmax[k] = rmax[k] = lmin[k] = rmin[k] = sum[k] = a[l];
    	}
    	else {
    		int mid = l + ((r - l) >> 1);
    		build(l,mid,k<<1);
    		build(mid+1,r,k<<1|1);
    		pushup(k);
    	}
    }
    
    void updata(int p,int v,int l,int r,int k) {
    	if(l == r) {
    		sum[k] = maxkey[k] = minkey[k] = v;
            lmax[k] = rmax[k] = lmin[k] = rmin[k] = v;
    	}
    	else {
    		int mid = l + ((r - l) >> 1);
    		if(p <= mid) {
    			updata(p,v,l,mid,k<<1);
    		}
    		else {
    			updata(p,v,mid+1,r,k<<1|1);
    		}
    		pushup(k);
    	}
    }
    
    
    int main()
    {
    	int n,m;
    	int u,v;
    	scanf("%d",&n);
    	for(int i = 1;i <= n; ++i) {
    		scanf("%d",&a[i]);
    	}
    	build(1,n,1);
    	scanf("%d",&m);
    	while(m--) {
    		scanf("%d%d",&u,&v);
    		updata(u,v,1,n,1);
    		int ans;
    		if(sum[1] == maxkey[1])
    			ans = sum[1] - minkey[1];
    		else
    			ans = max(maxkey[1],sum[1] - minkey[1]);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    使用 elementUI 的表单进行查询,表单中只有一个文本框时,回车会自动触发表单的提交事件,导致页面的刷新。
    Vue+elementUI 创建“回到顶部”组件
    elementUI 表格 table 的表头错乱问题
    阿拉伯数字转中文大写(整数)方法
    vue开发 回到顶部操作
    vue-cli 项目中使用 v-chart 及导出 chart 图片
    vue-router路由钩子
    vue随记
    vue中的watch
    Ajax 同步异步互相转换以及区别
  • 原文地址:https://www.cnblogs.com/Mangata/p/14295210.html
Copyright © 2011-2022 走看看