• 【洛谷 3178】树上操作


    题目描述

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

    • 操作 1 :把某个节点 x 的点权增加 a 。
    • 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    • 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    输入输出格式

    输入格式:

    第一行包含两个整数 N, M 。表示点数和操作数。
    接下来一行 N 个整数,表示树中节点的初始权值。
    接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。
    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    输出格式:

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    输入输出样例

    输入样例#1: 复制
    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3
    输出样例#1: 复制
    6
    9
    13

    说明

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

     题解:树链泼粪,上代码

    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long f[2001][2001];
    struct line
    {
         int s,t;
         long long x;
         int next;
    }a[4001];
    int head[2001];
    long long tmp[2001];
    int edge;
    inline void add(int s,int t,long long x)
    {
         a[edge].next=head[s];
         head[s]=edge;
         a[edge].s=s;
         a[edge].t=t;
         a[edge].x=x;
    }
    bool v[2001];
    int size[2001];
    int n,kk;
    inline void trdp(int d)
    {
         v[d]=true;
         size[d]=1;
         int i;
         int j,k;
         for(i=head[d];i!=0;i=a[i].next)
         {
              int t=a[i].t;
              if(!v[t])
              {
                   trdp(t);
                   for(j=0;j<=kk;j++)
                        tmp[j]=f[d][j];
                   for(j=0;j<=min(size[d],kk);j++)
                   {
                        for(k=0;k<=min(size[t],kk);k++)
                        {
                             if(j+k>kk)
                                  break;
                             //int m=j+k;
                             tmp[j+k]=max(tmp[j+k],f[d][j]+f[t][k]+a[i].x*(k*(kk-k)+(size[t]-k)*(n-kk-(size[t]-k))));
                        }
                   }
                   size[d]+=size[t];
                   for(j=0;j<=size[d];j++)
                        f[d][j]=max(f[d][j],tmp[j]);
              }
         }
    }
    int main()
    {
         scanf("%d%d",&n,&kk);
         int i;
         int s,t;
         long long x;
         for(i=1;i<=n-1;i++)
         {
              scanf("%d%d%lld",&s,&t,&x);
              edge++;
              add(s,t,x);
              edge++;
              add(t,s,x);
         }
         trdp(1);
         printf("%lld
    ",f[1][kk]);
         return 0; 
    }
  • 相关阅读:
    postman是如何使用的?
    PHPstudy如何在本地搭建多站点
    2017 电影推荐
    MySQL 约束、表连接、表关联、索引
    MySQL 基本语句(1)
    MySQL 数据类型
    Python3 基础
    【LOJ】 #2665. 「NOI2013」树的计数
    【LOJ】#2244. 「NOI2014」起床困难综合症
    【51nod】1251 Fox序列的数量
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11235260.html
Copyright © 2020-2023  润新知