zoukankan      html  css  js  c++  java
  • $NOIP 2015 Day2$ 模拟考试 题解报告

    (NOIP 2015 Day2) 模拟考试 题解报告

    得分情况

    (T1 100 Pts)

    (T2 90 Pts)

    (T3 15 Pts)

    总分: (205 Pts)

    考试过程

    太久了 快忘了...

    (T1) 用时比较短 半个小时左右 感觉可以了写 (T2)

    (T2) 一看就是 (DP) 写了半个小时 调了半个多小时 然后看 (T3)

    (T3) 先写的只有一条的时候 然后写链 写完之后查的时候发现写错了 然后调 然后 没调过来

    题解

    (T1) 跳石头

    二分答案 注意一下边界

    代码

    /*
      Time: 6.20
      Worker: Blank_space
      Source:
    */
    /*--------------------------------------------*/
    #include<cstdio>
    const int A = 5e4 + 7;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    /*------------------------------------常量定义*/
    inline void File() {
    	freopen("stone.in", "r", stdin);
    	freopen("stone.out", "w", stdout);
    }
    /*----------------------------------------文件*/
    int L, n, m, a[A], ans;
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    bool check(int x) {
    	int cnt = 0, pos = 0;
    	for(int i = 1; i <= n + 1; i++)
    	{
    		if(a[i] - a[pos] < x) cnt++;
    		else pos = i;
    	}
    	return cnt <= m;
    }
    /*----------------------------------------函数*/
    int main() {
    	File();
    	L = read(); n = read(); m = read(); a[n + 1] = L;
    	for(int i = 1; i <= n; i++) a[i] = read();
    	int l = 0, r = L;
    	while(l <= r)
    	{
    		int mid = l + r >> 1;
    		if(check(mid)) l = mid + 1, ans = mid;
    		else r = mid - 1;
    	}
    	printf("%d", ans);
    	return 0;
    }
    
    

    (T2) 子串

    状态: (f_{i, j, k, 0/1}) 表示考虑 (a) 串前 (i)(b) 串前 (j) 个 已经取了 (k) 个串 当前位置取不取 的方案数

    转移 不取的话直接继承 能取的话可以划分到上一个位置或自己再开一个串 累加方案数

    注意滚动数组空间优化 注意滚动数组的清空 注意初始化

    代码

    /*
      Time: 6.20
      Worker: Blank_space
      Source:
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<cstring>
    #define Abs(x) ((x) < 0 ? -(x) : (x))
    #define Max(x, y) ((x) > (y) ? (x) : (y))
    #define Min(x, y) ((x) < (y) ? (x) : (y))
    #define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
    /*--------------------------------------头文件*/
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    /*------------------------------------常量定义*/
    inline void File() {
    	freopen("substring.in", "r", stdin);
    	freopen("substring.out", "w", stdout);
    }
    /*----------------------------------------文件*/
    int n, m, l, f[2][210][210][2], sum;
    char a[1010], b[210];
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    
    /*----------------------------------------函数*/
    int main() {
    	File();
    	n = read(); m = read(); l = read();
    	scanf("%s%s", a + 1, b + 1);
    	for(int i = 1; i <= n; i++)
    	{
    		memset(f[i & 1], 0, sizeof f[i & 1]);
    		f[i & 1][1][1][0] = sum; if(a[i] == b[1]) f[i & 1][1][1][1] = 1, sum++;
    		for(int j = 2; j <= m; j++) for(int k = 1; k <= l; k++)
    		{
    			f[i & 1][j][k][0] = (f[i & 1][j][k][0] + f[i & 1 ^ 1][j][k][0] + f[i & 1 ^ 1][j][k][1]) % mod;
    			if(a[i] == b[j]) f[i & 1][j][k][1] = ((f[i & 1][j][k][1] + f[i & 1 ^ 1][j - 1][k - 1][0] + f[i & 1 ^ 1][j - 1][k - 1][1]) % mod + f[i & 1 ^ 1][j - 1][k][1]) % mod;
    		}
    	} 
    	printf("%d", (f[n & 1][m][l][0] + f[n & 1][m][l][1]) % mod);
    	return 0;
    }
    
    

    (T3) 运输计划

    时间取决于最长的一条路径 所以题目相当于在搞掉一条边之后使最长的一条路径最短

    可能从这里可以看出二分答案吧

    二分最大时间 检查所有路径 对于超过二分出的时间的路径通过差分进行统计 找出所有路径的交 从交中找出最长的一条边 不难发现 这条边一定在最长的一条路径上 每一次也只需要用最长的一条路径减去这条边 判断是否在二分出的时间内 所以需要预先求出最长的路径的长度 且需要多次用到点对之间的 (LCA) 可以提前预处理

    代码

    /*
      Time: 6.23
      Worker: Blank_space
      Source: P2680 [NOIP2015 提高组] 运输计划
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<cstring>
    #define mid (l + r >> 1)
    #define Max(x, y) ((x) > (y) ? (x) : (y))
    #define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
    /*--------------------------------------头文件*/
    const int B = 3e5 + 7;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    /*------------------------------------常量定义*/
    inline void File() {
    	freopen(".in", "r", stdin);
    	freopen(".out", "w", stdout);
    }
    /*----------------------------------------文件*/
    int n, m, dis[B], dep[B], top[B], fa[B], siz[B], son[B], max, c[B], d[B], cnt, _max, ans;
    struct node {int u, v, lca, w;} a[B];
    struct edge {int v, w, nxt;} e[B << 1];
    int head[B], ecnt;
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    void add_edge(int u, int v, int w) {e[++ecnt] = (edge){v, w, head[u]}; head[u] = ecnt;}
    void dfs1(int u, int pre) {
    	siz[u] = 1; fa[u] = pre; dep[u] = dep[pre] + 1;
    	for(int i = head[u]; i; i = e[i].nxt)
    	{
    		int v = e[i].v, w = e[i].w; if(v == pre) continue;
    		d[v] = w; dis[v] = dis[u] + w; dfs1(v, u); siz[u] += siz[v];
    		if(!son[u] || siz[son[u]] < siz[v]) son[u] = v;
    	}
    }
    void dfs2(int u, int tp) {
    	top[u] = tp; if(son[u]) dfs2(son[u], tp);
    	for(int i = head[u], v = e[i].v; i; i = e[i].nxt, v = e[i].v)
    		if(v != fa[u] && v != son[u]) dfs2(v, v);
    }
    int LCA(int x, int y) {
    	while(top[x] != top[y])
    	{
    		if(dep[top[x]] < dep[top[y]]) Swap(x, y);
    		x = fa[top[x]];
    	}
    	if(dep[x] > dep[y]) Swap(x, y);
    	return x;
    }
    void dfs(int u, int pre) {
    	for(int i = head[u]; i; i = e[i].nxt) if(e[i].v != pre) dfs(e[i].v, u), c[u] += c[e[i].v];
    	if(c[u] == cnt && d[u] > _max) _max = d[u];
    }
    bool check(int x) {
    	memset(c, 0, sizeof c); cnt = _max = 0;
    	for(int i = 1; i <= m; i++)
    		if(a[i].w > x) c[a[i].u]++, c[a[i].v]++, c[a[i].lca] -= 2, cnt++;
    	dfs(1, 0); return max - _max <= x;
    }
    /*----------------------------------------函数*/
    int main() {
    	n = read(); m = read();
    	for(int i = 1; i < n; i++)
    	{
    		int x = read(), y = read(), z = read();
    		add_edge(x, y, z); add_edge(y, x, z);
    	}
    	dfs1(1, 0); dfs2(1, 1);
    	for(int i = 1; i <= m; i++)
    	{
    		int x = read(), y = read(), z = LCA(x, y), k = dis[x] + dis[y] - 2 * dis[z];
    		a[i] = (node){x, y, z, k}; max = Max(max, k);
    	}
    	int l = 0, r = max;
    	while(l <= r)
    		if(check(mid)) ans = mid, r = mid - 1;
    		else l = mid + 1;
    	printf("%d", ans);
    	return 0;
    }
    

    很罕见的调都没调 写完一发 (A)

  • 相关阅读:
    Python自动化学习笔记(九)——Python的面向对象
    Python自动化学习笔记(八)——接口开发、发送网络请求、发送邮件、写日志
    MRWordCount
    环境变量追加命令
    hadoop退役旧数据节点
    Hadoop服役新数据节点
    Namenode文件损坏
    NameNode故障处理
    NN和2NN工作机制
    hdfs读写流程
  • 原文地址:https://www.cnblogs.com/blank-space-/p/14922847.html
Copyright © 2011-2022 走看看