zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    包和常用内置模块(二)
    常用内置模块(一)
    正则表达式和re模块
    迭代器和生成器
    函数(四)
    函数(三)闭包函数与装饰器
    Codeforces Round #539 (Div. 2) D 思维
    Codeforces Round #539 (Div. 2) 异或 + dp
    Codeforces Round #546 (Div. 2) E 推公式 + 线段树
    牛客练习赛42 C 反着计算贡献
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9902130.html
Copyright © 2011-2022 走看看