【NOIP2014 Day1 T2】联合权值

来源:互联网 发布:淘宝图片拍摄 编辑:程序博客网 时间:2024/06/06 15:04

【NOIP2014 Day1 T2】联合权值

Time Limit:10000MS  Memory Limit:131072K
Total Submit:57 Accepted:30 
Case Time Limit:1000MS

Description

 

Input

 

Output

 

Sample Input

51 22 33 44 51 5 2 3 10

Sample Output

20 74

Hint

 

Source

感谢nodgd放上题目


看了题解才能得全分。以中间点讨论

答案一:记录n个中间点的邻近的第一大数和第二大数,更新答案

答案二:sum记录距离中间点为一的权值和, powersum记录距离中间点为一的取值平方和

中间点周围的权值和=w[1]*(sum-w[1])+w[2]*(sum-w[2])+......+w[n]*(sum-w[n])

=(w[1]+w[2]+......w[n])*sum-(w[1]*w[1]+w[2]*w[2]+......w[n]*w[n])

=sum*sum-powersum


#include<cstdio>using namespace std;#define maxn 200009int u[maxn], v[maxn];long long w[maxn], first[maxn], second[maxn], sum[maxn], powersum[maxn];void add(int mid, long long w){sum[mid]+=w;powersum[mid]+=(w*w);if(w>first[mid])second[mid]=first[mid], first[mid]=w;else if(w>second[mid])second[mid]=w;}inline void _read(int& d){char t=getchar();bool f=false;while(t<'0'||t>'9') {if(t=='-') f=true; t=getchar();}for(d=0;t<='9'&&t>='0';t=getchar()) d=d*10+t-'0';if(f) d=-d;}inline void _read2(long long& d){char t=getchar();bool f=false;while(t<'0'||t>'9') {if(t=='-') f=true; t=getchar();}for(d=0;t<='9'&&t>='0';t=getchar()) d=d*10+t-'0';if(f) d=-d;}int main(){int i;int n;long long ans1=0, ans2=0;scanf("%d", &n);for(i=1; i<n; i++)_read(u[i]), _read(v[i]);for(i=1; i<=n; i++)_read2(w[i]);for(i=1; i<=n; i++)add(u[i], w[v[i]]), add(v[i], w[u[i]]);for(i=1; i<=n; i++){if(first[i]*second[i]>ans1)ans1=first[i]*second[i];ans2=((ans2+sum[i]*sum[i]-powersum[i])%10007+10007)%10007;}printf("%I64d %I64d", ans1, ans2);}


0 0