NOIP2015解题报告
来源:互联网 发布:php留言板视频教程 编辑:程序博客网 时间:2024/05/01 00:43
Day1.
当时的zxn很弱,弱到连dfs都调不明白就开始去NOIP。
现在他会了dfs,二分答案,求LCA,bfs,拓扑排序。
所以他回去填NOIP2015的题解坑。
T1.我现在依然不知道除了这种尾递归式的写法之外还有啥别的写法……
伪代码:
void dfs(int i,int j,int x){ if(满足条件)w[i][j] = x; dfs(i',j',x + 1);}
咳我好像现在明白了……
大概一个循环确实能搞出来……
T2.
求最小环,当时zxn心里确实也是这么想的。
由于他太弱了不会dfs,所以他并不知道怎么写。
题解:
dfs一遍,记一下时间戳。
void dfs(int x){ vis[x] = 1; tid[x] = ++ tim; RepG(i,x) if(!vis[v])dfs(v); else ans = min(ans,tid[x] - tid[v] + 1); //大概是这样的吧}
然后后来仔细一想,嗯我还是bfs吧。
次奥……?T掉了QAQ
嗯我们还是冷静一下,发现……
如果是bfs,需要拓扑排序,删掉没有用的那些点,只剩下环即可。
#include<algorithm>#include<cmath>#include<cstdio>#include<cstring>#define Rep(i,n) for(int i = 1; i <= n ; i ++)#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)#define RD(i,x,n) for(int i = x; i <= n ; i ++)#define CLR(a,b) memset(a,b,sizeof(a))#define v edge[i].tousing namespace std;int read(){ char ch = getchar(); while(ch < '0' || ch > '9')ch = getchar (); int x = 0; while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar (); return x;}int to[200005];bool vis[200005],vis_now[200005];int q[200005],tid[200005],tim = 0,ans = 1 << 30,end[200005];int main(){ int n = read(); Rep(i,n) { int a = read(); to[i] = a; end[to[i]] ++; } int h = 0,t = -1; Rep(i,n) if(!end[i])vis[q[++ t] = i] = 1; while(h <= t){ int x = q[h ++]; end[to[x]] --; if(!end[to[x]])vis[q[++ t] = to[x]] = 1; } Rep(i,n){ if(!vis[i]){ h = 0,t = -1; vis[i] = 1; q[++ t] = i; tim = 0; tid[i] = 0; while(h <= t){ int x = q[h ++]; if(!vis_now[to[x]])vis_now[q[++ t] = to[x]] = 1,tid[to[x]] = ++ tim,vis[to[x]] = 1; else ans = min(ans,tim - tid[to[x]] + 1),h = t + 1; } } } printf("%d\n",ans); return 0;}
QAQ当时明明知道标算然而就是写不出来?
T3.
斗地主。
张地主出的一道水题。张地主亲口说道:“NOIP的一道水题。”
张地主这次CTSC还出了一道提交答案题。
“我们可以发现第8个点是个网格图。”
“第九个点是除了前几个调换了下顺序之外的网格图。”
“第十个点是挖掉了一些点的网格图。”
whx:“我要吐槽!怎么检验它是网格图呢?”
“我的暴力spfa怎么跑的这么慢呢……?”
TAT
题解:
暴力搜索即可。
我们考虑对于当前的手牌,先枚举顺子应该会优一点,因为这样方便加最优性剪枝。
我们考虑:
if(ans <= depth )return;
加这个剪枝就过了。
#include<algorithm>#include<cmath>#include<cstdio>#include<cstring>#define Rep(i,n) for(int i = 1; i <= n ; i ++)#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)#define RD(i,x,n) for(int i = x; i <= n ; i ++)#define CLR(a,b) memset(a,b,sizeof(a))#define v edge[i].tousing namespace std;int s[20];int read(){ char ch = getchar(); while(ch < '0' || ch > '9')ch = getchar (); int x = 0; while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar (); return x;}int Cases,n,ans;void dfs(int now){ if(now >= ans)return; int a = 0,b = 0,c = 0; Rep_0(i,14)if(s[i] == 1)a ++; Rep_0(i,13)if(s[i] == 2)b ++; Rep_0(i,13) if(s[i] == 4){ c ++; if(a >= 2)a -= 2; else if(b >= 2)b -= 2; else if(b >= 1)b --; } Rep_0(i,13) if(s[i] == 3){ c ++; if(a >= 1)a --; else if(b >= 1)b --; } ans = min(ans,a + b + c + now); Rep_0(i,8){ int j; for(j = i ; j <= 11 ; j ++){ s[j] --; if(s[j] < 0)break; if(j - i >= 4)dfs(now + 1); } if(j == 12)j --; while(j >= i)s[j --] ++; } Rep_0(i,10){ int j; for(j = i; j <= 11; j ++){ s[j] -= 2; if(s[j] < 0)break; if(j - i >= 2)dfs(now + 1); } if(j == 12)j --; while(j >= i)s[j --] += 2; } Rep_0(i,11){ int j; for(j = i; j <= 11; j ++){ s[j] -= 3; if(s[j] < 0)break; if(j - i > 0)dfs(now + 1); } if(j == 12)j --; while(j >= i)s[j --] += 3; }}int main(){ Cases = read(),n = read(); while(Cases --){ CLR(s,0); ans = 10005; Rep(i,n){ int c = read(),col = read(); if(c < 3 && c)s[10 + c] ++; else if(c >= 3)s[c - 3] ++ ; else s[13] ++; } dfs(0); if(s[13] == 2)ans ++; printf("%d\n",ans); } return 0;}
当时NOIP的时候,zxn表示自己:
“这个可能是某种神奇的搜索,估计写不出来。”
mdzz。
Day2.
zxn:”day1好像挺水的,虽然我不会做,但是算法还是都看出来的。day2应该很友善.”
T1.
跳石头。
zxn:”什么叫二分答案???”
题解:我们对最终那个” 最小的距离最大” 进行二分答案。
也就是说,我们考虑二分那个值,判断是否可行。
现在问题在于怎么O(n)判断可行。
考虑现在有两块石头i和j(i < j )它们连在一起,现在它们的距离小于二分的答案,我们现在想一下该搬哪块……
嗯……
显然是搬走j更优。
我们现在需要考虑的仅仅是这个答案是否可行,所以我们现在面临的条件就是是否能让它花费的石头最少。
考虑这样:
i和j的距离小于二分的距离,并且j和j + 1的距离也小于二分距离。
我们肯定是要继续往后走的。
我们删去i的话以后影响的距离并不受这个i石头的控制,但是我们删去j了之后,不仅消除了前面的i - > j的不合法,而且还有可能让后面的变得合法。
所以删去石头j,即当前扫到的这个石头更优。
#include<algorithm>#include<cmath>#include<cstdio>#include<cstring>#define Rep(i,n) for(int i = 1; i <= n ; i ++)#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)#define RD(i,x,n) for(int i = x; i <= n ; i ++)#define CLR(a,b) memset(a,b,sizeof(a))#define v edge[i].tousing namespace std;int read(){ char ch = getchar(); while(ch < '0' || ch > '9')ch = getchar (); int x = 0; while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar (); return x;}int n,m,L;int dis[50005];bool check(int x){ int p = 0 ,k = 0; Rep(i,n + 1){ if(dis[i] - dis[k] < x)p ++; else k = i; if(p > m)return 0; } return 1;}int Bin_ans(int l,int r){ if(l == r)return l; int mid = l + r + 1 >> 1; if(check(mid))return Bin_ans(mid,r); return Bin_ans(l,mid - 1);}int main(){ L = read(),n = read(),m = read(); Rep(i,n) dis[i] = read(); dis[0] = 0; dis[n + 1] = L; printf("%d\n",Bin_ans(1,L)); return 0;}
T2.
zxn在一个月前不可置信地问fsf:”这怎么可能是一道特别简单的DP?”
现在他看到这道题:”哦我自己真是智障。”
设f[i][j][k]表示A串到i,B串到j,一共搞了k个串连起来的方案数。
前缀和 + 滚动数组优化。
这就没了啊QAQ
T3.
zxn原来一直读错题了。
他读成了使得所有的花费总和最小。
题解:使得最大的花费最小,显然二分答案。
问题是怎么check。
我们可以利用它的LCA。
我们考虑这两个点(u,v),如果dis(u,v) >ans,那是要担责任的。
我们把u - > v的路径都标一遍,表示它们用过一遍,并且我们把距离答案最大的差记为lim。
假设我们有p条边要担责任。
当有一条边a它的边权 >= lim,且有use[a] == p,那么我们就可以删掉它了。
总的复杂度我一开始以为这是个暴力,所以一直觉得自己不会做。
现在想想每次复杂度是可以优化成O(n)的啊QAQ
考虑我们每次只标一下那两个节点和它们的LCA。
我们直接对它们到LCA的路径都加一下就好了,但是如果每一个都单独加的话显然是不优的。
我们考虑其实这个玩意可以用dfs序优化一发,就是我们每次找叶子节点进行往上的递推。
这样就是O(n)的辣QAQ
总复杂度是O(
所以zxn还是太弱了QAQ
- NOIP2015 解题报告
- NOIP2015解题报告
- NOIP2015 day2 解题报告
- NOIp2015提高组 解题报告
- NOIP2015解题报告 By ljt12138
- noip2015运输计划解题报告
- NOIP2015提高组解题报告
- NOIP2015信息传递解题报告
- 解题报告 NOIP2015 信息传递
- 解题报告 NOIP2015 子串
- NOIP2015提高组复赛 解题报告
- NOIP2015 普及组(Junior) 解题报告
- NOIP2015 斗地主 解题报告(搜索)
- NOIP2015 子串 解题报告(DP)
- JZOJ.4300[NOIP2015模拟11.3]装饰大楼 解题报告
- JZOJ.4301[NOIP2015模拟11.3]备用钥匙 解题报告
- JZOJ.4302[NOIP2015模拟11.3]IOIOI卡片占卜 解题报告
- NOIP2015提高组Day2 第二题 子串 解题报告
- 浅谈差异化与同质化
- 敏捷软件开发第二部分(OCP:开放-封闭原则)
- 进程与线程的区别
- 【2016杭电女生赛1008】【数据结构 动态节点线段树】Claris Loves Painting
- PHP实习(三)
- NOIP2015解题报告
- BATCHSQL--GoldenGate Parameter
- 【java SE基础】Java线程详解
- asynctask
- LIBSVM在matlab下的使用安装
- Arduino 101 IMU测试及问题
- 【2016杭电女生赛1009】【挖掘本质找关系 模拟】sum 找到最小的正整数,满足a乘sum(n)==b乘S(2n)
- Hibernate_一级缓存_Demo
- Linux C笔记之 作用域 详解