zoukankan      html  css  js  c++  java
  • 【LOJ#3264】海报

    题目

    题目链接:https://loj.ac/p/3264

    (n,qleq 40000)

    思路

    最多能连续选 (3) 个人以及单点修改就已经把动态 dp 提示的非常明显了。
    我们可以通过枚举前 (3) 个人选或不选来把环上的问题转化为序列上的问题。等价于选出若干个人价值最小且相邻 (4) 个人中至少需要选择一个。那么直接维护一个 (4 imes 4) 的矩阵 ddp 随便搞搞就好了。
    时间复杂度 (O(Qk^3log n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=40010,M=4;
    const ll Inf=1e18;
    int n,Lim,Q,a[N];
    ll sum;
    
    int read()
    {
    	int d=0; char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    struct Matrix
    {
    	ll a[M+1][M+1];
    	Matrix() { memset(a,0x3f3f3f3f,sizeof(a)); }
    	
    	friend Matrix operator *(Matrix a,Matrix b)
    	{
    		Matrix c;
    		for (int i=1;i<=Lim;i++)
    			for (int j=1;j<=M;j++)
    				for (int k=1;k<=M;k++)
    					c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]);
    		return c;
    	}
    }res;
    
    struct SegTree
    {
    	Matrix f[N*4];
    	
    	void update(int x,int l,int r,int k)
    	{
    		if (l==r)
    		{
    			f[x].a[1][1]=a[l]; f[x].a[1][2]=0; f[x].a[1][3]=Inf; f[x].a[1][4]=Inf;
    			f[x].a[2][1]=a[l]; f[x].a[2][2]=Inf; f[x].a[2][3]=0; f[x].a[2][4]=Inf;
    			f[x].a[3][1]=a[l]; f[x].a[3][2]=Inf; f[x].a[3][3]=Inf; f[x].a[3][4]=0;
    			f[x].a[4][1]=a[l]; f[x].a[4][2]=Inf; f[x].a[4][3]=Inf; f[x].a[4][4]=Inf;
    			return;
    		}
    		int mid=(l+r)>>1;
    		if (k<=mid) update(x*2,l,mid,k);
    			else update(x*2+1,mid+1,r,k);
    		f[x]=f[x*2]*f[x*2+1]; 
    	}
    }seg;
    
    void solve()
    {
    	ll ans=Inf;
    	for (int s=0;s<8;s++)
    	{
    		ll ans1=0; int l=4,r=0;
    		for (int i=1;i<=3;i++)
    			if (s&(1<<i-1))
    			{
    				ans1+=a[i]; r=i;
    				if (l==4) l=i;
    			}
    		res.a[1][1]=res.a[1][2]=res.a[1][3]=res.a[1][4]=Inf;
    		res.a[1][4-r]=ans1;
    		Lim=1; res=res*seg.f[1]; Lim=M;
    		for (int i=1;l+i<=5;i++)
    			ans=min(ans,res.a[1][i]);
    	}
    	cout<<sum-ans<<"
    ";
    }
    
    int main()
    {
    	Lim=M;
    	n=read();
    	for (int i=1;i<=n;i++)
    	{
    		a[i]=read(); sum+=a[i];
    		if (i>=4) seg.update(1,4,n,i);
    	}
    	solve();
    	Q=read();
    	while (Q--)
    	{
    		int x;
    		x=read(); sum-=a[x];
    		a[x]=read(); sum+=a[x];
    		if (x>=4) seg.update(1,4,n,x);
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    java 开发之linux 下 tomcat
    Eclipse 工具栏不见了
    开始Java学习(Java之负基础实战)
    error: Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier
    真机调试iwatch
    创建iwatch 程序选项
    OC--类型为ID 的类的名称
    Cell.reuseIdentifier 指什么
    mongodb在win7下的安装和使用
    mongodb 常用命令
  • 原文地址:https://www.cnblogs.com/stoorz/p/15030043.html
Copyright © 2011-2022 走看看