Codeforces Round #288 (Div. 2)
来源:互联网 发布:剑三捏脸正太数据 编辑:程序博客网 时间:2024/06/05 23:51
A,B,C水
D。
有一个串,长度为n+2,
现在知道他的所有n个 长度为3的子串是什么
求出原始的串
这题跟POJ 2337有点像
最后抽象出的问题就是求欧拉通路:
将每个长度为3的子串, 前两个字母(数字)看成一个结点, 后两个字母(数字)看成一个结点,
然后这个子串就相当于 一条从前一个结点到后一个结点的边
欧拉通路的要求就是所有边都要走一遍, 所以最后就是求欧拉通路了
结点的个数最大为62*62,边的数量显然就是n了
因为两个字母(数字)hash成数字的话也就是62*62种
首先要判断这个欧拉通路是否存在
首先计算每个结点的入度和出度,
然后如果一个有向图存在欧拉通路。
则任意结点的出度跟入度的差的绝对值 不大于1
并且统计abs(出度-入度)==1 的结点的数量,假设为x个
则x必然为0或者2
如果为0个,则欧拉通路在任意一点都可当做起点
如果为2个,则欧拉通路从(出度-入度)==1 的结点出发
求欧拉通路的时候我们dfs即可,每条边会有一个编号,保证每条边只走一次。
但是需要注意的是,这个n是有20万的, 重边和自环多了会出一些问题。
所以我就将重边看成1条,但是对其计数,在dfs的时候用边的数量当做是否访问过的标记
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <cmath>#include <algorithm>#include <map>#include <ctime>#define MAXN 111111#define MAXM 1122222#define INF 1000000007#define eps 1e-8using namespace std;int n;typedef pair<int, int> PII;vector<PII> g[66 * 66];int num[66 * 66];int in[66 * 66], out[66 * 66];int fa[66 * 66], v[66 * 66];int en[66 * 66][66 * 66];int vis[222222], nv[222222];int st[222222];char s[211111][6];int find(int x) { if(x == fa[x]) return x; int t = find(fa[x]); fa[x] = t; return t;}void join(int x, int y) { int fx = find(x); int fy = find(y); if(fx != fy) fa[fx] = fy;}int getc(char c) { if(c >= 'a' && c <= 'z') return c - 'a'; if(c >= 'A' && c <= 'Z') return c - 'A' + 26; return c - '0' + 52;}int ind;void dfs(int u, int eid) { for(int i = 0; i < g[u].size(); i++) { int tid = g[u][i].second; if(vis[tid]) { vis[tid] --; dfs(g[u][i].first, tid); } } if(eid) st[ind++] = eid;}int main(){ scanf("%d", &n); for(int i = 0; i < 66 * 66; i++) fa[i] = i; for(int i = 1; i <= n; i++) { scanf("%s", s[i]); int a = getc(s[i][0]); int b = getc(s[i][1]); int c = getc(s[i][2]); int id1 = a * 62 + b; int id2 = b * 62 + c; v[id1] = 1; v[id2] = 1; join(id1, id2); if(en[id1][id2] == 0) en[id1][id2] = i, g[id1].push_back(PII(id2, i)); in[id2]++; out[id1]++; vis[en[id1][id2]]++; } int tmp = -1, flag = 0; for(int i = 0; i < 66 * 66; i++) { if(!v[i]) continue; if(tmp == -1) tmp = find(i); else { if(tmp != find(i)) { flag = 1; break; } } } int cnt = 0, src = -1; for(int i = 0; i < 66 * 66; i++) { if(!v[i]) continue; if(abs(in[i] - out[i]) >= 2) { flag = 1; break; } else if(abs(in[i] - out[i]) == 1) { cnt ++; if(out[i] - in[i] == 1) src = i; } } if(src == -1) src = tmp; if(flag) { printf("NO\n"); } else if(cnt == 0 || cnt == 2) { dfs(src, 0); printf("YES\n"); for(int i = ind - 1; i >= 0; i--) { int tid = st[i]; if(i == ind - 1) printf("%s", s[tid]); else printf("%c", s[tid][2]); } printf("\n"); } else { printf("NO\n"); } return 0;}
题意是
给出n个区间。 。
然后第i个区间表示的是第i个左括号与右括号的 下标距离范围
求出一个合法的括号序列 并且满足这些范围
然后后来想了想,貌似是个记忆化dp, 而且并不难。。
令dp[i][j]表示第i个到第j个左括号是否都成功的匹配到了右括号
那么在dfs的时候,对于dp[i][j] , 我们枚举i被第几个右括号匹配了,显然是从第i个右括号枚举到第j个右括号,假设被第k个右括号匹配并且满足之前给的范围了
然后就可以去寻找其子状态 dp[i + 1][k] 以及dp[k+1][j]
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <cmath>#include <algorithm>#include <map>#include <ctime>#define MAXN 111111#define MAXM 1122222#define INF 1000000007#define eps 1e-8using namespace std;int dp[666][666];int l[666], r[666];char s[3333];int n;int p[3333];int dfs(int L, int R) { if(L > R) return 1; if(dp[L][R]) return dp[L][R]; for(int i = L; i <= R; i++) { if(i - L + 1 >= l[L] && i - L + 1 <= r[L] ) { if(dfs(L + 1, i) == 1 && dfs(i + 1, R) == 1) { p[L] = (i - L) * 2 + 1; return dp[L][R] = 1; } } } return dp[L][R] = -1;}int main(){ scanf("%d", &n); int flag = 1; for(int i = 1; i <= n; i++) { scanf("%d%d", &l[i], &r[i]); if(l[i] % 2 == 0) l[i]++; if(r[i] % 2 == 0) r[i]--; if(l[i] > r[i]) { flag = 0; } l[i] = (l[i] + 1) / 2; r[i] = (r[i] + 1) / 2; } if(flag == 0) { printf("IMPOSSIBLE\n"); return 0; } dfs(1, n); if(dp[1][n] != 1) { printf("IMPOSSIBLE\n"); return 0; } int j = 0; for (int i = 1 ; i <= n; i++){ while(s[j]) ++j; s[j] = '('; s[j + p[i]] = ')'; } puts(s); return 0;}
- Codeforces Round #288 (Div. 2)
- Codeforces Round#288(Div.2)
- Codeforces Round #288 (Div. 2)
- Codeforces Round #288 (Div. 2)
- Codeforces Round #288 (Div. 2)
- Codeforces Round #288 (Div. 2)
- Codeforces Round #288 (Div. 2)
- Codeforces Round #288 (Div. 2) 合集
- Codeforces Round #288 (Div. 2) ABC
- Codeforces Round #288 (Div. 2) 总结
- Codeforces Round #288 (Div. 2) 题解
- Codeforces Round #102 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #104 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #107 (Div. 2)
- LeetCode-Sort Colors
- c语言命名
- How does HTTP file upload work?
- android-async-http
- Android 自定义View步骤
- Codeforces Round #288 (Div. 2)
- Linux网络设置(参考国嵌视频)
- 作用域
- EF细节处提高性能
- ruby遍历map
- Integer与int的种种比较你知道多少?
- Ant混淆打包生成SDK的JAR包
- 使用FTP服务器(Working with FTP Servers)
- Java 本地缓存的实现(转)