zoukankan      html  css  js  c++  java
  • 【JZOJ6287】扭动的树

    description


    analysis

    • 区间(DP),首先按照键值排个序,这样保证树的中序遍历就为原序列

    • (f[0][i][j])表示([i..j])区间作为([unknown..i-1])右儿子的最大和,(f[1][i][j])就是([i..j])区间作为([j+1..unknown])左儿子

    • 预处理(f)的初值是很明显的,然后(O(n^2log))预处理出两两数之间的(gcd)

    • 对于一段区间([i..j]),枚举中转点(k),表示([i..k-1],[k+1,j])分别作为(k)的左右儿子

    • (k=i)(k=j)特殊转移,(i<k<j)可知([i..j])可由(f[1][i][k-1],f[0][k+1][j])转移得到

    • 具体转移到(0)(1)取决于(a[k])(a[i-1],a[j+1])是否符合条件((gcd>1)


    code

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #define MAXN 305
    #define INF 1000000007 
    #define ll long long
    #define reg register ll
    #define fo(i,a,b) for (reg i=a;i<=b;++i)
    #define fd(i,a,b) for (reg i=a;i>=b;--i)
    
    using namespace std;
    
    ll f[2][MAXN][MAXN];
    ll g[MAXN][MAXN];
    ll sum[MAXN];
    ll n,ans=-INF;
    
    struct node
    {
    	ll x,y;
    }a[MAXN];
    
    inline ll read()
    {
    	ll x=0,f=1;char ch=getchar();
    	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    inline ll max(ll x,ll y){return x>y?x:y;}
    inline bool cmp(node a,node b){return a.x<b.x;}
    inline ll get(ll x,ll y){return sum[y]-sum[x-1];}
    inline ll gcd(ll x,ll y){return x%y==0?y:gcd(y,x%y);}
    int main()
    {
    	freopen("T2.in","r",stdin);
    	//freopen("tree.in","r",stdin);
    	//freopen("tree.out","w",stdout);
    	n=read();
    	fo(i,0,n)fo(j,0,n)f[0][i][j]=f[1][i][j]=-INF;
    	fo(i,1,n)a[i].x=read(),a[i].y=read();
    	sort(a+1,a+n+1,cmp);
    	fo(i,1,n)fo(j,1,n)g[i][j]=gcd(a[i].x,a[j].x);
    	fo(i,1,n)
    	{
    		sum[i]=sum[i-1]+a[i].y;
    		if (i!=1 && g[i][i-1]>1)f[0][i][i]=a[i].y;
    		if (i!=n && g[i][i+1]>1)f[1][i][i]=a[i].y;
    	}
    	fo(len,2,n)
    	{
    		fo(i,1,n-len+1)
    		{
    			ll j=i+len-1,tmp;
    			fo(k,i,j)
    			{
    				if (k==i)tmp=f[0][i+1][j]+get(i,j);
    				else if (k==j)tmp=f[1][i][j-1]+get(i,j);
    				else tmp=f[1][i][k-1]+f[0][k+1][j]+get(i,j);
    				if (i!=1 && g[k][i-1]>1)f[0][i][j]=max(f[0][i][j],tmp);
    				if (j!=n && g[k][j+1]>1)f[1][i][j]=max(f[1][i][j],tmp);
    				if (n==len)ans=max(ans,tmp);
    			}
    		}
    	}
    	printf("%lld
    ",ans<0?-1ll:ans);
    	return 0;
    }
    
  • 相关阅读:
    angular.isDefined()
    angular.isDate()
    angular.isArray()
    .NET中栈和堆的比较
    SQL Server 2012配置Always On可用性组
    一分钟了解负载均衡的一切
    C# 线程并发锁
    获取Http请求参数
    什么是WCF
    Bitmap算法应用
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11329709.html
Copyright © 2011-2022 走看看