NOIP2014 提高组复赛解题报告

本文是关于2014年NOIP提高组复赛的解题报告,详细分析了1002. 联合权值、1003. Flappy Bird、1005. 寻找路径、1006. 解方程四道题目,涉及树形DP、背包DP、最短路和高精度计算等算法,分享了解题思路与优化技巧。
摘要由CSDN通过智能技术生成

NOIP2014 提高组复赛


day1

这里写图片描述

1002. 联合权值

  • 树形dp

想用树形dp进行收集的时候,把儿子们的信息给重新收集一遍了,还用了邻接表(甚至本来想用vector)。实际上在收集的时候只要维护权值总和以及最大权值就好了,而不需要再把所有儿子重新提出来再处理。因为这个地方没有优化结果TLE了三组……qvq

但是简直比Tyvj的模拟题还水……好歹人家有五个点……

按照树形dp的思想,我们统计经过当前子树的根的,这棵子树内符合条件的三元点对数目。那么对于这个根,它有两种情况:

  • 根是三元点对中的中间结点,此时两端节点是它的儿子中的任意一对。
  • 根是三元点对中的两端节点,此时另一端节点是它的孙子。

这样显然是不会重复的,因为我们只考虑当前子树的情况(即不考虑父亲和祖父节点等的情况),并且一定收集包含根结点的三元点对。那么我们只需要统计孙子节点和儿子节点的权值和与最大权值(孙子节点的数据在以儿子节点为根的时候已经收集到了),于是时间复杂度为 O(n)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define M 200005
#define P 10007
#define clear(x,val) memset(x,val,sizeof(x))
using namespace std;
template <class temp>
inline void Rd(temp &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>47);
}
inline void Mod(int &a,int b){a+=b;if(a>=P)a-=P;}
//-----------------------
int n,w[M];
int head[M],htop=0;
struct node{
  int v,nxt;}Nodes[M<<1];
int mxson[M],sumson[M];
void add_edge(int u,int v){
    Nodes[++htop]=(node){v,head[u]};head[u]=htop;
    Nodes[++htop]=(node){u,head[v]};head[v]=htop;
}
int val,mx=0,ans=0;
void dfs(int u,int pre){
    for(int j=head[u];~j;j=Nodes[j].nxt){
        int v=Nodes[j].v;
        if(v==pre)continue;
        dfs(v,u);
        mx=max(mxson[u]*w[v],mx);
        if(mxson[u]<w[v])mxson[u]=w[v];
        Mod(ans,sumson[u]*w[v]%P);
        Mod(sumson[u],w[v]);

        mx=max(mxson[v]*w[u],mx);
        Mod(ans,sumson[v]*w[u]%P);
    }
}
int main(){
    clear(head,-1);
    Rd(n);
    for(int i=1,u,v;i<n;i++)
        Rd(u),Rd(v),add_edge(u,v);
    for(int i=1;i<=n;i++)Rd(w[i]);
    dfs(1,0);
    Mod(ans,ans);
    printf("%d %d\n",mx,ans);
}

如果不从正常的树形dp考虑,那么我们就枚举每个点作为中心节点的情况,此时它周围一圈的相邻节点中均可以构成两端点对。于是每次统计一下,时间复杂度为 O(n)

1003. Flappy Bird

  • 背包dp

玩Codevs的玩了这么久还A不掉也是可以。又是受了上次NOIP2013_day2_task3华容道那题的影响……居然肛在选择dfs还是bfs好久……然而我一开始还是敲了dfs qvq,真的害怕如果标程又是dfs,然后我居然写了bfs,那时候我会哭的一脸懵逼的。

后来硬是改成了Dijkstra,想想复杂度有点高于是准备改成队列……虽然没改成功,但是我最后意识到——这题是不是可以用背包做。 qvq 但是硬是水了75分,比暴力背包高(难道完全背包的优化不暴力么……)。

bfs还是简单的,只不过由于每次转移的边权在 [0,m] 中,不是恒定的1,所以只能用堆弹。时间复杂度为 O(n×m2logn)</

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值