[Offer收割]编程练习赛29
来源:互联网 发布:能以礼让为国乎 编辑:程序博客网 时间:2024/05/16 06:24
逃离迷宫4
题解
题目求解
代码
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <unordered_set>#include <vector>#define FIN freopen("input.txt", "r", stdin)#define FOUT freopen("output.txt", "w", stdout)using namespace std;typedef long long LL;const int MAXN = 4e5 + 5;const int INF = 0x3f3f3f3f;bool flag;int x, y;void gcd(int a, int b) { while(a != 0 && b != 0) { if(a == x && b == y || b == x && a == y) { flag = true; break; } if(a > b) { int t = a / b; if(t > 2){ a = a - b * (t - 2); } a = a - b; } else { int t = b / a; if(t > 2){ b = b - a * (t - 2); } b = b - a; } }}int a, b;int main() { int _, a, b; scanf("%d", &_); while(_ --) { scanf("%d%d%d%d", &x, &y, &a, &b); flag = false; gcd(a, b); puts(flag ? "YES" : "NO"); } return 0;}
最大得分
题解
由题目可以知道,总共存在最多
其中
map
来维护数字和出现的个数,并且保证它有序,那么代码
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <unordered_set>#include <vector>#include <map>#include <unordered_map>#define FIN freopen("input.txt", "r", stdin)#define FOUT freopen("output.txt", "w", stdout)using namespace std;typedef long long LL;const int MAXN = 1e3 + 5;const int INF = 0x3f3f3f3f;int N, M;int A[MAXN];int dp[MAXN][MAXN];map<int, int> Mii;vector<pair<int, int> > vpii;int main() { while(~scanf("%d%d", &N, &M)) { Mii.clear(); for(int i = 1; i <= N; i ++) { scanf("%d", &A[i]); Mii[A[i]] ++; } memset(dp, 0, sizeof(dp)); vpii.clear(); vpii.push_back(make_pair(-10, 0)); for(map<int, int>::iterator it = Mii.begin(); it != Mii.end(); it ++) { vpii.push_back(make_pair(it -> first, it -> second)); } for(int i = 1; i < vpii.size() ; i ++) { for(int k = 1; k <= M; k ++) { for(int j = i - 1; j >= 0; j --) { dp[i][k] = max(dp[i][k], dp[i - 1][k]); if(vpii[i].first - vpii[j].first > 1) { dp[i][k] = max(dp[i - 1][k], dp[j][k - 1] + vpii[i].first * vpii[i].second); break; } } //printf("%d, %d : [%d]\n", i, k, dp[i][k]); } } printf("%d\n", dp[vpii.size() - 1][M]); } return 0;}
本质不同的回文子串的数量
题解
跟求不同回文子串的数目有点类似,不过这次不能统计相同的,所以我们同样用马拉车处理出回文子串的数目,然后用后缀数组处理出相邻的后缀的最长公共前缀,很明显拥有相同前缀的子串是会重复的,所以用一个临时变量维护已经计算过的子串长度,然后后面加的时候减去它就可以得到正确结果,个人用的模板是挑战程序设计竞赛上的后缀数组,因为非常好理解。
代码
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <unordered_set>#include <vector>#include <map>#include <unordered_map>#define FIN freopen("input.txt", "r", stdin)#define FOUT freopen("output.txt", "w", stdout)using namespace std;typedef long long LL;const int MAXN = 8e5 + 5;const int INF = 0x3f3f3f3f;char S[MAXN], tS[MAXN << 1];int len[MAXN << 1], sz;int rank_[MAXN << 1], tmp[MAXN << 1], lcp[MAXN << 1], sa[MAXN << 1];int g_k;void mlc(){ sz = 0; int ln = strlen(S); tS[sz ++] = '$'; for(int i = 0;i < ln;i ++){ tS[sz ++] = '#'; tS[sz ++] = S[i]; } tS[sz ++] = '#'; tS[sz] = '@'; int mx = 0, id = 0; len[0] = 1; for(int i = 1;i < sz;i ++){ if(mx > i){ len[i] = min(len[2 * id - i], mx - i); } else{ len[i] = 1; } while(tS[i + len[i]] == tS[i - len[i]]) len[i] ++; if(len[i] + i > mx){ mx = len[i] + i; id = i; } }}bool compare_sa(int i, int j){ if(rank_[i] != rank_[j]) return rank_[i] < rank_[j]; else { int ri = i + g_k <= sz ? rank_[i + g_k] : -1; int rj = j + g_k <= sz ? rank_[j + g_k] : -1; return ri < rj; }}void construct_sa(){ for(int i = 0;i <= sz;i ++){ sa[i] = i; rank_[i] = i < sz ? tS[i] : -1; } for(g_k = 1;g_k <= sz;g_k <<= 1){ sort(sa, sa + sz + 1, compare_sa); tmp[sa[0]] = 0; for(int i = 1;i <= sz;i ++){ tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0); } for(int i = 0;i <= sz;i ++){ rank_[i] = tmp[i]; } }}void construct_lcp(){ for(int i = 0;i <= sz;i ++) rank_[sa[i]] = i; int h = 0; lcp[0] = 0; for(int i = 0;i < sz;i ++){ int j = sa[rank_[i] - 1]; if(h > 0) h --; for(;j + h < sz && i + h < sz;h ++){ if(tS[j + h] != tS[i + h]) break; } lcp[rank_[i] - 1] = h; }}void solve(){ mlc(); construct_sa(); construct_lcp(); int t = 0, ans = 0; for(int i = 1;i <= sz;i ++){ int f = sa[i]; t = min(t, lcp[i - 1]); if(len[f] <= t) continue; ans += (len[f] - t) / 2; t = len[f]; } printf("%d\n", ans);}int main(){ while(~scanf("%s", S)){ memset(len , 0, sizeof(len)); memset(rank_, 0, sizeof(len)); memset(tmp, 0, sizeof(tmp)); memset(lcp, 0, sizeof(lcp)); memset(sa, 0, sizeof(sa)); solve(); }}
阅读全文
0 0
- [Offer收割]编程练习赛29
- [Offer收割]编程练习赛1
- hiho[Offer收割]编程练习赛1
- 2016 [Offer收割]编程练习赛3
- [Offer收割] 编程练习赛3
- [Offer收割]编程练习赛4
- [Offer收割]编程练习赛4
- [Offer收割]编程练习赛7
- [Offer收割]编程练习赛4
- [Offer收割]编程练习赛8
- [Offer收割]编程练习赛3
- [Offer收割]编程练习赛10
- hihocoder [Offer收割]编程练习赛19
- hihocoder [Offer收割]编程练习赛24
- [Offer收割]编程练习赛24
- [Offer收割]编程练习赛26
- [Offer收割]编程练习赛31
- [Offer收割]编程练习赛27
- yum install mysql5.x
- Oracle导入包含clob字段的dmp文件报错问题解决办法
- checkbox的回显, 打上对勾却无法保存到后台用模拟点击解决 ,等问题总结angluarjs
- 一个手咪按键,检测抬起和按下的思考
- WebSocket与消息推送
- [Offer收割]编程练习赛29
- 在web环境下搭建shiro框架
- mysql查看用户权限
- CSA云计算关键领域安全指南4.0 (中文版)
- 解决Zepto.js不支持animate报错的问题,错误信息$(...).animate is not a function
- Java实现ftp上传下载功能
- C++&UDP&Http的数据传输
- Bean基本概念的实现
- Windows上安装Maven