11.02T2 区间DP+最值优化

#3872 扭动的树

 

描述

有一棵以key为键值以val为权值的二叉查找树,定义其某个节点的sum为它的子树内节点的val之和。给出n个(key, val)正整数对,现需保证这棵树上任意一条边的两个端点的key值的最大公约数不为1,询问这棵树上所有节点的sum之和最大可能是多少。如果这棵树不存在任意一个合法形态,输出-1。

输入

输入文件名为tree.in。

第一行为一个整数n。

接下来n行每行两个正整数ki vi。保证ki互不相同。

输出

输出文件名为tree.out。

输出仅一行一个整数表示答案。

样例输入[复制]
4
2 3
6 4
9 8
12 1
样例输出[复制]
51
提示

对于1号测试点(5%):k_1=1。

对于1~3号测试点(15%):1≤n≤10。

对于1~10号测试点(50%):1≤n≤50。

对于11~14号测试点(20%):所有ki的gcd不为1。

对于1~18号测试点(100%):1≤n≤300,1≤k_i≤〖10〗^18,1≤v_i≤〖10〗^6。

标签
ZYH
 
 
 
 
区间DP,注意左右的最大值才有意义,同之前的机器人
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define N 100005
 5 using namespace std;
 6 struct node{
 7     long long key,val;
 8 }e[N];
 9 long long f[2][301][301],sum[400];
10 long long g[301][301];
11 bool cmp(const node&a,const node&b){
12     return a.key<b.key;
13 }
14 long long gcd(long long a,long long b){
15     if(a<b)swap(a,b);
16     while(a=a%b)swap(a,b);
17     return b;
18 }
19 int main(){
20     for(int i=0;i<=1;i++)for(int j=1;j<=300;j++)for(int k=1;k<=300;k++)f[i][j][k]=-0x7fffffffffffffll;
21     long long n;
22     cin>>n;
23     for(int i=1;i<=n;i++){
24         cin>>e[i].key>>e[i].val;
25     }
26     sort(e+1,e+n+1,cmp);
27     for(int i=1;i<=n;i++){
28         for(long long j=1;j<=n;j++){
29             g[i][j]=gcd(e[i].key,e[j].key);
30         }
31     }
32     for(int i=1;i<=n;i++){
33         sum[i]=sum[i-1]+e[i].val;
34         if(i!=1&&g[i][i-1]!=1)f[0][i][i]=e[i].val;
35         if(i!=n&&g[i][i+1]!=1)f[1][i][i]=e[i].val;
36     }
37     long long max0=-0x7fffffffffffffll,Dp;
38     for(int Len=2;Len<=n;Len++){
39         for(int l=1,r;l+Len-1<=n;l++){
40             r=l+Len-1;
41             for(int u=l;u<=r;u++){
42                 if(u==l)Dp=f[0][l+1][r]+(sum[r]-sum[l-1]);
43                 if(u==r)Dp=f[1][l][r-1]+(sum[r]-sum[l-1]);
44                 if(l<u&&u<r)Dp=f[1][l][u-1]+f[0][u+1][r]+(sum[r]-sum[l-1]);
45                 if(l!=1&&g[u][l-1]!=1)f[0][l][r]=max(f[0][l][r],Dp);
46                 if(r!=n&&g[u][r+1]!=1)f[1][l][r]=max(f[1][l][r],Dp);
47                 if(Len==n)max0=max(max0,Dp);
48             }
49         }
50     }
51     if(max0<0)cout<<"-1";
52     else cout<<max0;
53     return 0;
54 }

over

posted @ 2018-11-03 21:13  saionjisekai  阅读(263)  评论(0编辑  收藏  举报