Gym101341题解
Posted RDCのACM奇幻之旅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym101341题解相关的知识,希望对你有一定的参考价值。
难度分类
(div2A-B):B C D G H M
(div2C-D):E K
( div2E ):A J I
喵喵喵:F L
A.
B.
题意:给一个长度为2~2e5的串,交换两个字符,要求最后没有"happiness"
坑点:本来没有"happiness",交换一把,出现了“happiness”,这下好!
code1:(比赛时的,一点也不典雅~)
#include <iostream> #include <vector> #include <cstring> using namespace std; char s[500000+10]; vector<int> v; int main() { scanf("%s", s+1); int n = strlen(s+1); for(int i=1;i+8<=n;i++) { if(s[i] == \'h\' && s[i+1] == \'a\' && s[i+2] == \'p\' && s[i+3] == \'p\' && s[i+4] == \'i\' && s[i+5] == \'n\'&& s[i+6] == \'e\' && s[i+7] == \'s\' && s[i+8] == \'s\') { v.push_back(i); } } if(v.size() == 0) { printf("YES\\n"); for(int i=2;i<=n;i++) { swap(s[1], s[i]); int gg = 0; if(i+8<=n && s[i] == \'h\' && s[i+1] == \'a\' && s[i+2] == \'p\' && s[i+3] == \'p\' && s[i+4] == \'i\' && s[i+5] == \'n\'&& s[i+6] == \'e\' && s[i+7] == \'s\' && s[i+8] == \'s\') { gg = 1; } if(1+8<=n && s[1] == \'h\' && s[2] == \'a\' && s[3] == \'p\' && s[4] == \'p\' && s[5] == \'i\' && s[6] == \'n\'&& s[7] == \'e\' && s[8] == \'s\' && s[9] == \'s\') { gg = 1; } if(gg == 0) { printf("%d %d\\n", 1, i); return 0; } swap(s[1], s[i]); } } if(v.size() == 1) { printf("YES\\n"); printf("%d %d\\n", v[0], v[0]+1); } if(v.size() == 2) { printf("YES\\n"); printf("%d %d\\n", v[0], v[1]+1); } if(v.size() > 2) { printf("NO\\n"); } }
code2: 待补。。。
C.
题意:给a个红球,b个绿球,c个不知道颜色的球,问,保证拿出的球中,红球
不超过n,绿球不超过m,最多能拿几个球。
solve: 比赛时读错题了,懵逼了半天。
如果a+c>n,那么拿n+1个球有可能GG.
如果b+c>m,那么拿m+1个球有可能GG.
code:
#include <iostream> using namespace std; typedef long long LL; LL ans = 0; int main() { LL a, b, c, m, n; cin >> a >> b >> c >> n >> m; ans = a + b + c; if(a+c > n) ans = min(n, ans); if(b+c > m) ans = min(m, ans); cout << ans << endl; }
D.
题意:一只蛤,在一根线上跳,每次可以跳的距离给出了,问能否跳到目标。
坑点:负数和0的特判
#include <iostream> using namespace std; typedef long long LL; LL gcd(LL a, LL b) { return b==0?a:gcd(b, a%b); } int n; LL x, ans, k; int main() { cin >> n >> k; for(int i=1;i<=n;i++) { scanf("%I64d", &x); if(x<0) x = -x; if(i==1) ans = x; if(x==0) continue; ans = gcd(ans, x); } if(k % ans == 0) cout << "YES"; else cout << "NO"; }
E.
题意:数轴上有n个可以互相传送的点,和m个宝石。移动1个距离,-1s,传送门之间相互传送不消耗时间
问吃完所有宝石最小耗费。
solve:
hint 1:离散化.
hint 2:传送门i与传送门(i+1)之间的宝石,有2种处理方式。
a) 从一个门直接移动到另一个门。时间耗费为| p[i+1]-p[i] |.
b) 相邻宝石最大间距为maxlen,时间耗费为 2 * (| p[i+1]-p[i] | - maxlen).
画个图,更好理解!
#include <iostream> #include <algorithm> #include <map> #include <vector> using namespace std; typedef long long LL; const int NICO = 200000 + 10; int n, m; LL t[NICO], b[NICO]; vector<LL> v; map<LL, int> mp; int main() { scanf("%d %d", &n, &m); for(int i=1;i<=n;i++) { scanf("%I64d", &t[i]); v.push_back(t[i]); } t[0] = -1e16, t[n+1] = 1e16; int pos = 1; for(int i=1;i<=m;i++) { scanf("%I64d", &b[i]); v.push_back(b[i]); } sort(v.begin(), v.end()); for(int i=0;i<v.size();i++) { mp[v[i]] = i; } LL ans = 2L * (v[v.size() - 1] - v[0]); for(int i=1;i<n;i++) { int l = mp[t[i]], r = mp[t[i+1]]; LL mx = 0; for(int j=l;j<r;j++) { mx = max(mx, v[j+1] - v[j]); } mx = mx*2L; mx = max(mx, t[i+1] - t[i]); ans -= mx; } cout << ans << endl; }
F.
G.
题意:gay里gay气的CF...... 一群人,如果A对B产生了爱慕之情,A就将自己的name改成I_love_B.
按时间顺序给出了一些爱慕的关系,问1号,最终的name是什么。
题解:逆向来一遍就行了。
#include <iostream> using namespace std; const int NICO = 200000 + 10; int n, m, u, v; char s[NICO][40]; int a[NICO], b[NICO]; int main() { scanf("%d", &n); for(int i=1;i<=n;i++) { scanf("%s", s[i]); } scanf("%d", &m); for(int i=1;i<=m;i++) { scanf("%d %d", &a[i], &b[i]); } int need = 1; for(int i=m;i>=1;i--) { if(a[i] == need) { printf("I_love_"); need = b[i]; } } printf("%s\\n", s[need]); }
H.
题意:一个矩阵,拿掉一个十字架(莫名想到硫磺火),让剩下的数字中最大值最小,求最小值~
题解:预处理,求出每个元素左上,左下,右上,右下最小值。
#include <iostream> using namespace std; const int NICO = 1002; int n, m; int a[NICO][NICO], l[NICO][NICO], r[NICO][NICO]; int lu[NICO][NICO], ld[NICO][NICO], ru[NICO][NICO], rd[NICO][NICO]; int main() { scanf("%d %d", &n, &m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d", &a[i][j]); } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { l[i][j] = max(l[i][j-1], a[i][j]); } for(int j=m;j>=1;j--) { r[i][j] = max(r[i][j+1], a[i][j]); } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { lu[i][j] = max(l[i][j], lu[i-1][j]); ru[i][j] = max(r[i][j], ru[i-1][j]); } } for(int i=n;i>=1;i--) { for(int j=1;j<=m;j++) { ld[i][j] = max(l[i][j], ld[i+1][j]); rd[i][j] = max(r[i][j], rd[i+1][j]); } } int ans = 1e9+7, cx = -1, cy = -1; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { int t1 = max(lu[i-1][j-1], ru[i-1][j+1]); int t2 = max(ld[i+1][j-1], rd[i+1][j+1]); int t3 = max(t1, t2); if(t3 < ans) { cx = i, cy = j; ans = t3; } } } printf("%d %d\\n", cx, cy); }
I.
J. (炒鸡好玩的一道题)
题意:给一颗树,两个人准备制定好路线,准备抓一个怪物,这个怪物跑得很快。
并且知道了两人路线。问有没有可能抓到怪物。
题解:
hint 1: A守住重要隘口,B遍寻涯角~ 这就是我们大致的思路。
图画的好恐怖。。。。。。。。。。。。。。。
A守住1,然后B把两个圈圈里面的点扫一遍即可。
hint 2: 然后我们发现,A要守的节点必须是链状的。B要访问的每一个分支,也
得是链状的。
有趣的结论:从叶子节点向上删点,删到出现岔路为止。然后判断接下来的剩下的
图是不是一根链即可。
code:
1 #include <iostream> 2 #include <vector> 3 #include <set> 4 using namespace std; 5 const int NICO = 200000 + 10; 6 int n, u, v, deg[NICO], flag[NICO]; 7 vector<int> vec[NICO]; 8 void dfs(int x, int p) 9 { 10 flag[x] = 1; 11 for(int i=0;i<vec[x].size();i++) 12 { 13 if(vec[x][i] == p) continue; 14 if(deg[vec[x][i]] <= 2) 15 { 16 dfs(vec[x][i], x); 17 } 18 } 19 } 20 int main() 21 { 22 scanf("%d", &n); 23 for(int i=1;i<n;i++) 24 { 25 scanf("%d %d", &u, &v); 26 vec[u].push_back(v); 27 vec[v].push_back(u); 28 deg[u] ++, deg[v] ++; 29 } 30 for(int i=1;i<=n;i++) 31 { 32 if(deg[i] > 1) continue; 33 int t = i; dfs(t, -1); 34 } 35 36 for(int i=1;i<=n;i++) 37 { 38 if(flag[i]) continue; 39 int cnt = 0; 40 for(int j=0;j<vec[i].size();j++) 41 { 42 if(flag[vec[i][j]]) continue; 43 cnt ++; 44 } 45 if(cnt >= 3) 46 { 47 printf("NO\\n"); 48 return 0; 49 } 50 } 51 printf("YES\\n"); 52 53 }
K.
L.
M.
贪心!每次选GG的人从最后面拿,为前面腾出空间即可。
#include <iostream> #include <vector> using namespace std; const int NICO = 200000 + 10; typedef long long LL; LL sum = 0; int a[NICO], n; vector<int> v1, v2; int main() { scanf("%d", &n); for(int i=1;i<=n;i++) { scanf("%d", &a[i]); sum += a[i]; } if(sum > n) { printf("NO\\n"); return 0; } int ok = 1; int pos = n; for(int i=n;i>=1;i--) { if(a[i] > 0) { for(int j=pos;j>=pos-a[i]+1;j--) { if(i >= j) ok = 0; v1.push_back(i); v2.push_back(j); } } pos = pos-a[i]; } if(ok == 0) { printf("NO\\n"); return 0; } printf("YES\\n"); for(int i=0;i<v1.size();i++) { printf("%d %d\\n", v1[i], v2[i]); } }
以上是关于Gym101341题解的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Gym101341I:Matrix God(随机化构造矩阵降维)***