zoukankan      html  css  js  c++  java
  • NOIp 2014 联合权值 By cellur925

    题目传送门

    这题自己(真正)思考了很久(欣慰)。

    (轻而易举)地发现这是一棵树后,打算从Dfs序中下功夫,推敲了很久规律,没看出来(太弱了)。

    开始手动枚举距离为2的情况,模模糊糊有了一些概念,但没有总结。(敲黑板:题目中发现规律与重要性质注意总结!

    其实,距离为2的情况只有两种:祖父/兄弟。

    一个小时后放弃治疗。开始想暴力,很好想,我们对于每个点,枚举他的出边,再在每个出边中的出边中进行枚举,储存距离为2 的点。期望得分60pts.

    大力交了一下:40pts,AC*6,WA*2,MLE*4.

    MLE还有情可缘,vector开动态数组可能炸了,WA的那两个喵喵喵?

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 #include<vector>
     5 
     6 using namespace std;
     7 typedef long long ll;
     8 
     9 int n,tot;
    10 ll sum,ans,p=10007;
    11 int head[200090];
    12 ll val[200090];
    13 bool vis[200090];
    14 struct node{
    15     int to,next;
    16 }edge[400090];
    17 vector<int>law[200090];
    18 
    19 void add(int x,int y)
    20 {
    21     edge[++tot].to=y;
    22     edge[tot].next=head[x];
    23     head[x]=tot;
    24 }
    25 
    26 
    27 void dfs(int u)
    28 {
    29     for(int i=head[u];i;i=edge[i].next)
    30     {
    31         int v=edge[i].to;
    32         for(int j=head[v];j;j=edge[j].next)
    33         {
    34             int g=edge[j].to;
    35             if(g==u) continue;
    36             law[u].push_back(g);
    37         }
    38     }
    39 }
    40 
    41 int main()
    42 {
    43     scanf("%d",&n);
    44     for(int i=1;i<=n-1;i++)
    45     {
    46         int x=0,y=0;
    47         scanf("%d%d",&x,&y);
    48         add(x,y);
    49         add(y,x);
    50     }
    51     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    52 //    dfs_pre(1);
    53 //    memset(vis,0,sizeof(vis));
    54 //    dfs(1,0);
    55     for(int i=1;i<=n;i++)
    56         dfs(i);
    57     for(int i=1;i<=n;i++)
    58     {
    59         for(int j=0;j<law[i].size();j++)
    60         {
    61             int u=i,v=law[i][j];
    62             ll tmp=val[u]%p*val[v]%p;
    63             (sum+=tmp)%=p;
    64             (ans=max(ans,tmp))%=p;
    65         }
    66     }
    67     printf("%lld %lld",ans,sum);
    68     return 0;
    69 }
    View Code

    后来经过冷静分析看题解发现并不需要存儿子,当时每次更新一下就行了。而且最大值并不需要取膜。

    再交一下60pts。TLE4个点,正常。

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 #include<vector>
     5 
     6 using namespace std;
     7 typedef long long ll;
     8 
     9 int n,tot;
    10 ll sum,ans,p=10007;
    11 int head[200090];
    12 ll val[200090];
    13 struct node{
    14     int to,next;
    15 }edge[400090];
    16 
    17 void add(int x,int y)
    18 {
    19     edge[++tot].to=y;
    20     edge[tot].next=head[x];
    21     head[x]=tot;
    22 }
    23 
    24 
    25 void dfs(int u)
    26 {
    27     for(int i=head[u];i;i=edge[i].next)
    28     {
    29         int v=edge[i].to;
    30         for(int j=head[v];j;j=edge[j].next)
    31         {
    32             int g=edge[j].to;
    33             if(g==u) continue;
    34             ans=max(ans,val[u]*val[g]);
    35             (sum+=val[u]*val[g])%=p; 
    36         }
    37     }
    38 }
    39 
    40 int main()
    41 {
    42     scanf("%d",&n);
    43     for(int i=1;i<=n-1;i++)
    44     {
    45         int x=0,y=0;
    46         scanf("%d%d",&x,&y);
    47         add(x,y);
    48         add(y,x);
    49     }
    50     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    51 //    dfs_pre(1);
    52 //    memset(vis,0,sizeof(vis));
    53 //    dfs(1,0);
    54     for(int i=1;i<=n;i++)
    55         dfs(i);
    56     printf("%lld %lld",ans,sum);
    57     return 0;
    58 }
    View Code

    正解:我们只需要枚举每个点与他相连的每一条边即可,统计出与每个点相邻的最大点值与次大点值,全局最值用(最大点值*次大点值)更新,全局和用“乘法分配律“”维护。

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 using namespace std;
     5 typedef long long ll;
     6 
     7 int n,tot;
     8 ll p=10007,sum,ans;
     9 int head[200090],val[200090];
    10 struct node{
    11     int to,next;
    12 }edge[400090];
    13 
    14 void add(int x,int y)
    15 {
    16     edge[++tot].to=y;
    17     edge[tot].next=head[x];
    18     head[x]=tot;
    19 }
    20 
    21 ll llmax(ll a,ll b)
    22 {
    23     if(a>=b) return a;
    24     else return b;
    25 }
    26 
    27 void update(int x)
    28 {
    29     int maxx=0,maxs=0;
    30     ll cnt=0;
    31     for(int i=head[x];i;i=edge[i].next)
    32     {
    33         int y=edge[i].to;
    34         if(val[y]>maxx) maxs=maxx,maxx=val[y];
    35         else if(val[y]>maxs) maxs=val[y];
    36         (sum+=cnt*val[y])%=p;
    37         (cnt+=val[y])%=p;
    38     }
    39     ans=llmax(ans,maxs*maxx);
    40 }
    41 
    42 int main()
    43 {
    44     scanf("%d",&n);
    45     for(int i=1;i<=n-1;i++)
    46     {
    47         int x=0,y=0;
    48         scanf("%d%d",&x,&y);
    49         add(x,y);add(y,x);
    50     }
    51     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    52     for(int i=1;i<=n;i++) update(i);
    53     printf("%lld %lld",ans,2*sum%p);
    54     return 0;
    55 } 
    View Code
  • 相关阅读:
    在main函数中使用django模型(附django正反向的外键关联查询)
    使用正则表达式替换文本内容
    spring 上下文和spring mvc上下文和web应用上下文servletContext之间的关系
    idea快捷键
    Spring MVC的jar包版本问题
    Spring MVC的参数类型转换
    HiddenHttpMethodFilter进行请求过滤,实现Rest风格的url
    Spring MVC的异常处理
    Spring MVC 的拦截器
    @ResponseBody&@RequestBody
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9505149.html
Copyright © 2011-2022 走看看