Day1:
T1:模拟;
#include
#include
#include
#include
#include
#include
#include
#include
#include
T2:
这次noip2016最难的题?
考场上只急着打暴力了,没有好好思考;
实际上想了之后还是很简单的;
这题的关键是理清思路,题目上的特点是 若一条路径已走的时间若与当前节点的值相等,这一点的答案加1;
最暴力的思路当然是dfs Q遍,先判断这个点是否在这条路径上,然后判断已走的距离是不是等于当前点的权值,都符合的话ans++;
如何化简条件?
我们可以发现当若有一条从x->y的路径是一条链,且dep[x]<dep[y],则若dep[i]-dep[x]=v[i],则该点ans++;
这可以变形成dep[i]-v[i]=dep[x],左边只与点i自身有关;
经过了这样的转化,我们发现可以这样做,将一个路径拆成从x->lca和lca->y两个链,然后可以仿照上面的方法,用dep与v[i]的关系做。
但做到了这一步仍然没什么卵用;
我们是否可以把目光转移,从看一条路径到看每个点?
对每个点而言,我们需要计算的是,它自身dep[i]±v[i]正好匹配经过它的路径所要求的的值的路径的数目;
这很绕,实际上对路径只有两个要求,第一个是经过它,第二个是路径与这个点可以匹配;
怎么维护?
第一个,维护只经过它的路径的值的集合;
第二个,在集合中快速找到符合要求的值的数目;
满足这两个要求,第一个可以用离线的方法维护,第二个可以在dfs的途中顺便维护一个桶,这个桶里存的就是经过它的路径的值的集合,然后可以O(1)查询;
这里面还有一个地方需要注意,每次桶从一颗子树出来的时候会带着这颗子树的信息,再进入另一个桶的时候会出现问题,解决方案是作差,先记录一下当前的ans值,待遍历完所有子树,再记录一下当前的ans,两个的差值即为所求;
在大佬眼里就是道水题…
#include
#include
#include
#include
#include
#include
#include
#include
#include
顺便进行了一下求lca的速度测试:
只求LCA的话,树链剖分最快,tarjan次之,倍增最慢(经常被卡);
还需要一些附加信息的话,tarjan无法处理,树链剖分效率很好,倍增效率太低;
代码长度上,树链剖分最长,lca次之,tarjan最短;
如果考场上只求lca的话,建议tarjan,很好写;
T3:
无力吐槽,这题让一心一意备考noip的人怎么受得了;
概率dp;
把概率扒下来其实就是一背包动规;
具体的还是自己去体会(看代码)……
#include
#include
#include
#include
#include
#include
#include
#include
#include
Day2:
T1:
组合数,考场脑子一抽写了二维树状数组,但实际也没什么问题(实际这题的二维动规是有一定的风险的,有人因此挂了);
#include
#include
#include
#include
#include
#include
#include
#include
#include
T2:
数学题目,需要证一下单调性(求个导如何?)
#include
#include
#include
#include
#include
#include
#include
#include
#include
T3:
惭愧惭愧,考场不假思索,先打暴力……
后改记忆化,本质上都是状压dp;
吐槽的是,我同学写正解都被卡了一个n,而我写dfs,没有被卡掉……
实质上dfs会避免访问很多不可能出现的状态,所以效率比较高;
#include
#include
#include
#include
#include
#include
#include
#include
#include