比赛-暑假训练赛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\n", 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\n", 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\n"); 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\n", 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

原文地址:https://www.cnblogs.com/ghcred/p/9375116.html

时间: 2024-10-01 07:29:16

比赛-暑假训练赛1 (26 Jul, 2018)的相关文章

2015暑假训练赛个人赛(8.19)

    ID Origin Title 二分+dp 22 / 89 Problem A UVALive 5983 MAGRID 枚举 19 / 44 Problem B UVALive 5984 Save the Students! ? 1 / 1 Problem C UVALive 5985 Robbing Gringotts ? 38 / 117 Problem D UVALive 5986 Wizarding Duel 预处理前2000个数 65 / 127 Problem E UVALi

2015暑假训练赛团体赛(8.3)

    ID Origin Title     12 / 37 Problem A UVALive 4763 Sudoku Extension   23 / 80 Problem B UVALive 4764 Bing it       Problem C UVALive 4765 String of Candied Haws     4 / 19 Problem D UVALive 4766 Gold Mines       Problem E UVALive 4767 Machine Tra

2015暑假训练赛个人赛(7.31)

    ID Origin Title 59 / 211 Problem A UVALive 6318 The New President 71 / 156 Problem B UVALive 6319 No Name   38 / 127 Problem C UVALive 6320 Encrypted Password 87 / 127 Problem D UVALive 6321 Kids Love Candies 1 / 20 Problem E UVALive 6322 The Swa

2018-2019赛季多校联合新生训练赛第六场(2018/12/15)补题题解

A 价钱统计(基础编程能力) 这个考点还是比较个性的,怎么四舍五入 解法 常规的讲如果四舍五入整数位的话,那么只需要在后面加个0.5然后强制转换一下就可以了 这个却要我们保留一位小数的四舍五入,那该怎么做呢 实际上我们只需要把这个数乘以10然后加0.5,强制转换后再除以10就可以了 代码 #include <bits/stdc++.h> using namespace std; double trans(double a) { a*=10; a+=0.5; a=int(a); a/=10; r

2018-2019赛季多校联合新生训练赛第八场(2018/12/22)补题题解

感慨 这次有点感冒,昏迷程度比较大中途还溜了 感谢 感谢qut的同学的帮助!!! A 小X与三角形(数学) 公式 两边的和-两边的差-1 因为边最小得大于两边的差,边最大得小于两边的和所以说求得是一个开区间内元素的个数 代码 #include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); ll a,

哈理工2015暑假训练赛BNU16488 Easy Task(简单题)

A - Easy Task Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu SubmitStatusPracticeZOJ 2969 Description Calculating the derivation of a polynomial is an easy task. Given a function f(x) , we use (f(x))' to denote its derivatio

哈理工2015 暑假训练赛 zoj 2976 Light Bulbs

Light BulbsTime Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu SubmitStatusPracticeZOJ 2976 Description Wildleopard had fallen in love with his girlfriend for 20 years. He wanted to end the long match for their love and get marri

哈理工2015暑假训练赛 zoj 2078Phone Cell

Phone CellTime Limit:10000MS    Memory Limit:32768KB    64bit IO Format:%lld & %llu SubmitStatusPracticeZOJ 2978 Description Nowadays, everyone has a cellphone, or even two or three. You probably know where their name comes from. Do you. Cellphones c

2015暑假训练赛个人赛(8.5)

  ID Origin Title   96 / 114 Problem A UVALive 4167 Parity  水题1 60 / 124 Problem B UVALive 4168 Lampyridae Teleportae  水题3 3 / 11 Problem C UVALive 4169 Hex Tile Equations   17 / 41 Problem D UVALive 4170 The Bridges of San Mochti   16 / 36 Problem E