• P3097 [USACO13DEC]Optimal Milking G(线段树维护矩阵乘法)


    题意简述:给定n个点排成一排,每个点有一个点权,多次改变某个点的点权并将最大点独立集计入答案,输出最终的答案

    定义f(i,0)为第i个数不取,定义f(i,1)为第i个数取。

    转移式子:

    f(i,0)=max(f(i-1,0),f(i-1,1))
    f(i,1)=max(f(i-1,0)+a[i])

    可以用矩阵表示这个过程:
    0 a[i]
    0 -inf

    用线段树维护一下这个矩阵乘法,就做完了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    typedef long long ll;
    struct matrix {
    	ll m[3][3];
    };
    void ccpy (matrix &x,matrix &y) {
    	for (int i=1;i<=2;i++) {
    		for (int j=1;j<=2;j++) {
    			x.m[i][j]=y.m[i][j];
    		}
    	}
    }
    void mul (matrix &ans,matrix a,matrix b) {
    	for (int i=1;i<=2;i++) {
    		for (int j=1;j<=2;j++) {
    			ans.m[i][j]=max(a.m[i][j],b.m[i][j]);
    		}
    	}
    	for (int k=1;k<=2;k++) {
    		for (int i=1;i<=2;i++) {
    			for (int j=1;j<=2;j++) {
    				ans.m[i][j]=max(ans.m[i][j],a.m[i][k]+b.m[k][j]);
    			}
    		}
    	}
    }
    int n,a[maxn],m;
    struct node {
    	int l,r;
    	matrix sum;
    }segTree[maxn<<2];
    void build (int i,int l,int r) {
    	segTree[i].l=l;
    	segTree[i].r=r;
    	if (l==r) {
    		segTree[i].sum.m[1][1]=0;
    		segTree[i].sum.m[1][2]=a[l];
    		segTree[i].sum.m[2][1]=0;
    		segTree[i].sum.m[2][2]=-1e10;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(i<<1,l,mid);
    	build(i<<1|1,mid+1,r);
    	mul(segTree[i].sum,segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    void up (int i,int p,int v) {
    	if (segTree[i].l==p&&segTree[i].r==p) {
    		a[segTree[i].l]=v;
    		segTree[i].sum.m[1][1]=0;
    		segTree[i].sum.m[1][2]=v;
    		segTree[i].sum.m[2][1]=0;
    		segTree[i].sum.m[2][2]=-1e10;
    		return;
    	}
    	int mid=(segTree[i].l+segTree[i].r)>>1;
    	if (p<=mid) up(i<<1,p,v);
    	if (p>mid) up(i<<1|1,p,v);
    	mul(segTree[i].sum,segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    int main () {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) scanf("%d",a+i);
    	long long ans=0;
    	build(1,1,n);
    	while (m--) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		up(1,x,y);
    		ans+=max(segTree[1].sum.m[1][1],segTree[1].sum.m[1][2]);
    	}
    	printf("%lld
    ",ans);
    }
  • 相关阅读:
    用自己的算法实现startsWith和endsWith功能
    随机生成4位验证码,由用户输入并验证是否输入正确,如果输入错误就生成新的验证码让用户重新输入,最多输入5次
    二分法(网上查找结果)
    模拟摇奖:从1-36中随机抽出8个不重复的数字
    冒泡排序
    输入年龄输出年龄段
    水仙花数
    百钱买百鸡
    百马百担的问题
    控制台输出九九乘法表
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15039523.html
Copyright © 2020-2023  润新知