zoukankan      html  css  js  c++  java
  • 比赛-暑假训练赛1 (26 Jul, 2018)

    A. 密码 没有想到题解里机智的 P2-P1 避免重复计算,我以为是一个类似最长公共子串的 DP,OrzOrzOrz。 设输入分别为 A, B 两个字符串。f[i][j] 表示 A 串前 i 位与 B 串前 j 位匹配( B 串中字母可以依次在 A 中找到)的方案数。 当 A[i] == B[j], f[i][j] = f[i-1][j-1] 当 A[i] != B[j], f[i][j] = f[i-1][j] 。 显然 f[i][0] = i 。然后直接这样写会爆空间,注意到 i 这维可以滚动掉。答案是 ∑f[i][lenB] 。

    B. 独立集 如果 i < j 且 A[i] < A[j] ,那么 i, j 就不会连边,就能够放在一个集合里。再推一下会发现第一问是求最长上升子序列。第二问可以脑补出这个东西:某个点确定的充要条件是:原序列以它为最后一个元素和第一个元素的单升,都有且仅有 1 个。后者可以转换为:反过来的序列里以它为最后一个元素的单降有且仅有 1 个。把 for 反着写然后让A[i] = -A[i],就把反向单降转化得和正向单升一样了。

    C. 益智游戏 先跑最短路,然后枚举边 x->y = w,对 dis(A, x) + w + dis(y, B) = dis(A, B) 且 dis(C, x) + w + dis(y, D) = dis(C, D) 的边做一个标记。显然最终的点都在这些边上。然后问题转化为求最长链+1(点数)。可以用 DP,f[x] = max{ f[i] } + 1 (满足有边从 i 到 x) 。其实写起来是记忆化搜索。由于上次做过一道什么轰炸城市的题,也是求最长链,被大佬们告知直接 topsort 就可以了不用搜索,所以考试的时候写了发 topsort 。另外样例第 2 组就是菊花图,会卡掉 SPFA (因为边数有 200000,非常大)。

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 long long f[250];
     5 char A[320000], B[250];
     6 
     7 int main()
     8 {
     9     long long ans = 0;
    10     int Alen, Blen, i, j;
    11     scanf("%s%s", A+1, B+1);
    12     Alen = strlen(A+1), Blen = strlen(B+1);
    13     for (i = 1; i <= Alen; ++i) {
    14         f[0] = i;
    15         for (j = Blen; j >= 1; --j)
    16             if (A[i] == B[j]) f[j] = f[j-1];
    17         ans += f[Blen];
    18     }
    19     printf("%lld
    ", ans);
    20     return 0;
    21 }
    A
     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <string.h>
     4 
     5 using namespace std;
     6 
     7 const int _N = 120000;
     8 const int INF = 1e9;
     9 
    10 int A[_N], f[_N], X[_N], Y[_N], cnt[_N];
    11 
    12 int main()
    13 {
    14     int i, N, len;
    15     scanf("%d", &N);
    16     for (i = 1; i <= N; ++i)
    17         scanf("%d", &A[i]);
    18     f[len = 0] = -INF;
    19     for (i = 1; i <= N; ++i) {
    20         if (A[i] > f[len]) { f[++len] = A[i], X[i] = len; continue; }
    21         int p = lower_bound(f+1, f+1+len, A[i])-f;
    22         f[p] = A[i], X[i] = p;
    23     }
    24     printf("%d
    ", len);
    25     f[len = 0] = -INF;
    26     for (i = N; i >= 1; --i) {
    27         if (-A[i] > f[len]) { f[++len] = -A[i], Y[i] = len; continue; }
    28         int p = lower_bound(f+1, f+1+len, -A[i])-f;
    29         f[p] = -A[i], Y[i] = p;
    30     }
    31     for (i = 1; i <= N; ++i)
    32         if (X[i]+Y[i]-1 == len) ++cnt[X[i]];
    33     for (i = 1; i <= N; ++i)
    34         if (X[i]+Y[i]-1 == len && cnt[X[i]] == 1) printf("%d ", i);
    35     return 0;
    36 }
    B
     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <vector>
     4 #include <queue>
     5 
     6 using namespace std;
     7 
     8 typedef long long ll;
     9 
    10 const int _N = 55005;
    11 const ll INF = 1e15;
    12 
    13 struct edge {
    14     int v; ll w;
    15     edge(int v = 0, ll w = 0):
    16         v(v), w(w) { }
    17     bool operator < (edge const &tmp) const
    18     {
    19         return w > tmp.w;
    20     }
    21 };
    22 
    23 vector<edge> G[3][_N];
    24 priority_queue<edge> Q;
    25 queue<edge> Q2;
    26 int N, M, beg1, end1, beg2, end2, ind[_N];
    27 ll dis1[_N], dis2[_N], anti1[_N], anti2[_N];
    28 bool mk[_N];
    29 
    30 void Ins(int id, int x, int y, ll w) { G[id][x].push_back(edge(y, w)); return; }
    31 
    32 void Dijkstra(int id, int beg, ll *dis)
    33 {
    34     int i;
    35     for (i = 1; i <= N; ++i) dis[i] = INF;
    36     dis[beg] = 0;
    37     while (!Q.empty()) Q.pop();
    38     Q.push(edge(beg, dis[beg]));
    39     while (!Q.empty()) {
    40         int p = Q.top().v;
    41         vector<edge>::iterator it;
    42         if (Q.top().w != dis[p]) { Q.pop(); continue; }
    43         for (it = G[id][p].begin(); it != G[id][p].end(); ++it) {
    44             if (dis[it->v] <= dis[p] + it->w) continue;
    45             dis[it->v] = dis[p] + it->w;
    46             Q.push(edge(it->v, dis[it->v]));
    47         }
    48         Q.pop();
    49     }
    50     return ;
    51 
    52 }
    53 
    54 int main()
    55 {
    56     int i, j;
    57     scanf("%d%d", &N, &M);
    58     for (i = 1; i <= M; ++i) {
    59         int x, y; ll w;
    60         scanf("%d%d%lld", &x, &y, &w);
    61         Ins(0, x, y, w), Ins(1, y, x, w);
    62     }
    63     scanf("%d%d%d%d", &beg1, &end1, &beg2, &end2);
    64     Dijkstra(0, beg1, dis1), Dijkstra(0, beg2, dis2);
    65     Dijkstra(1, end1, anti1), Dijkstra(1, end2, anti2);
    66     if (dis1[end1] >= INF || dis2[end2] >= INF) { printf("-1
    "); return 0; }
    67     for (i = 1; i <= N; ++i)
    68         for (j = G[0][i].size()-1; j >= 0; --j) {
    69             edge p = G[0][i][j];
    70             if (dis1[i] >= INF || dis2[i] >= INF || anti1[p.v] >= INF || anti2[p.v] >= INF) continue;
    71             if (dis1[i]+p.w+anti1[p.v] == dis1[end1] && dis2[i]+p.w+anti2[p.v] == dis2[end2])
    72                 Ins(2, i, p.v, p.w), ++ind[p.v];
    73         }
    74     for (i = 1; i <= N; ++i)
    75         if (!ind[i])
    76             Q2.push(edge(i, 1));//-------------------------
    77     ll ans = 0;
    78     while (!Q2.empty()) {
    79         edge p = Q2.front(); Q2.pop();
    80         ans = max(ans, p.w);
    81         for (int i = G[2][p.v].size()-1; i >= 0; --i) {
    82             int t = G[2][p.v][i].v;
    83             if (!--ind[t]) Q2.push(edge(t, p.w+1));
    84         }
    85     }
    86     printf("%lld
    ", ans);
    87     return 0;
    88 }
    C
    A密码
    时间限制 : 10000 MS   空间限制 : 165536 KB
    评测说明 : 1s
    问题描述

    假发通过了不懈的努力,得到了将军家门锁的密码(一串小写英文字母)。但是假发被 十四和猩猩他们盯上了,所以假发需要把密码传递出去。因为假发不想十四他们发现几松门 前贴的小纸条就是将军家的密码,所以他加密了密码(新八:听起来有点诡异)。加密方法 如下:随机地,在密码中任意位置插入随机长度的小写字符串。 不过,假发相信银桑和他那么多年小学同学,一定能猜中密码是什么的(新八:银桑什 么时候成攮夷志士了!!!)。可是,写完了小纸条之后,假发觉得有点长,就想截去头和 尾各一段(可以为空),让剩下的中间那一段依然包含真~密码。想着想着,假发就想知道 有多少种可行方案。结果在沉迷于稿纸之际,假发被投进了狱门岛(新八:……)。于是, 就由你计算了。

    输入格式

    两行非空字符串,纯小写英文字母,第一行是加密后的密码,第二行是原密码。
    第一行长度不超过 300000,第二行不超过 200。 

    输出格式

    一行,有多少种方案。注意:不剪也是一种方案。

    样例输入 1


    abcabcabc 
    cba

    样例输出 1

    9

    样例输入 2

    abcabcabac 
    cba

    样例输出 2

    18

    提示

    【样例1解释】 用(L,R)表示一种方案,其中L和R分别表示截去头和尾的长度。这9钟方案分别是 (0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)。 

    B独立集
    时间限制 : 20000 MS   空间限制 : 165536 KB
    评测说明 : 1s
    问题描述

    输入格式

    输入包含两行,第一行为 N,
    第二行为 1 到 N 的一个全排列

    输出格式

    输出包含两行,第一行输出最大独立集的大小,第二行从小到大输出一定在最大独立集 的点的编号。 

    样例输入 1
    样例输出 1
    样例输入 2

    15
    4 14 9 12 11 1 5 6 2 7 13 15 8 10 3

    样例输出 2

    6
    7 8 10 

    样例输入 3


    3 1 2

    样例输出 3

    2
    2 3

    提示

    30%的数据满足 N<=16
    60%的数据满足 N<=1,000
    100%的数据满足 N<=100,000

     
    C益智游戏
    时间限制 : 10000 MS   空间限制 : 165536 KB
    评测说明 : 1s
    问题描述

    小 P 和小 R 在玩一款益智游戏。游戏在一个正权有向图上进行。 小 P 控制的角色要从 A 点走最短路到 B 点,小 R 控制的角色要从 C 点走最短路到 D 点。 一个玩家每回合可以有两种选择,移动到一个相邻节点或者休息一回合。 假如在某一时刻,小 P 和小 R 在相同的节点上,那么可以得到一次特殊奖励,但是在每 个节点上最多只能得到一次。 求最多能获得多少次特殊奖励。 

    输入格式

    第一行两个整数 n,m 表示有向图的点数和边数。 接下来 m 行每行三个整数 xi,yi,li,表示从 xi到 yi有一条长度为 li的边。 最后一行四个整数 A,B,C,D,描述小 P 的起终点,小 R 的起终点。

    输出格式

    输出一个整数表示最多能获得多少次特殊奖励。若小 P 不能到达 B 点或者小 R 不能到达 D 点则输出-1。

    样例输入

    5 5 
    1 2 1 
    2 3 2 
    3 4 4 
    5 2 3 
    5 3 5 
    1 3 5 4

    样例输出


    2

    提示

    【数据规模】
    对于 30%的数据,满足 n≤50
    对于 60%的数据,满足 n≤1000,m≤5000 对于
    100%的数据,满足 n≤50000,m≤200000,1≤li≤500000000

  • 相关阅读:
    centos 安装netstat
    du 常见的命令
    CentOS7 安装Python3.6.8
    Alpine安装telnet
    TypeError: 'NoneType' object is not callable
    docker中删除dead状态的容器
    监控进程,线程shell脚本
    pyinstaller打包py成exe后音乐文件播放异常pygame.error failed to execute script
    lambda expressions
    Domain logic approaches
  • 原文地址:https://www.cnblogs.com/ghcred/p/9375116.html
Copyright © 2011-2022 走看看