Codeforces Round #442 (Div. 2)【solved : 6 / 6】
来源:互联网 发布:产品矩阵是什么意思 编辑:程序博客网 时间:2024/06/06 01:16
A - Alex and broken contest (water)
#include <bits/stdc++.h>using namespace std;char a[][20] = {"Danil", "Olya", "Slava", "Ann", "Nikita"};char s[105];bool judge(int id, int st, int sublen){ for(int i = 0; i < sublen; i++) if(s[st + i] != a[id][i]) return false; return true;}int main(){ scanf("%s", s); int len = strlen(s), cnt = 0; for(int i = 0; i < 5; i++) { int sublen = strlen(a[i]); for(int j = 0; j + sublen - 1 < len; j++) { if(judge(i, j, sublen)) cnt++; } } puts(cnt == 1 ? "YES" : "NO"); return 0;}
B - Nikita and string (思维)
题意:给你一个只包含a、b的子串,让选出一个子序列,满足第一部分全为a,第二部分全为b,第三部分全为a(各个部分可为空),问你这个子序列最长为多少。串长5000。
思路:用前缀和维护a的数量。然后枚举前两个部分的长度,即可。
#include <bits/stdc++.h>using namespace std;const int maxn = 5000 + 5;char s[maxn];int cnta[maxn];int main(){ scanf("%s", s + 1); int len = strlen(s + 1); for(int i = 1; i <= len; i++) cnta[i] = cnta[i - 1] + (s[i] == 'a'); int ans = 0; for(int i = 0; i <= len; i++) { for(int j = 0; i + j <= len; j++) { int cnt1 = cnta[i]; int cnt2 = j - (cnta[i + j] - cnta[i]); int cnt3 = cnta[len] - cnta[i + j]; ans = max(ans, cnt1 + cnt2 + cnt3); } } printf("%d\n", ans); return 0;}
C - Slava and tanks (构造)
题意:一排1*n的方格,每个方格内都有坦克,每个坦克被攻击第一次的时候会往两侧逃逸,被攻击第二次时被击毁。请给出方案,使得用最少的攻击方式,击毁所有坦克。
n≤100000
思路:将偶数位依次攻击一遍,所有的坦克逃至奇数位,再攻击一遍奇数位,击毁原先逃逸的坦克,然后存活的坦克逃至偶数位,再攻击一遍偶数位即可。
#include <bits/stdc++.h>using namespace std;int main(){ int n; scanf("%d", &n); vector<int>vec; for(int i = 2; i <= n; i+=2) vec.push_back(i); for(int i = 1; i <= n; i+=2) vec.push_back(i); for(int i = 2; i <= n; i+=2) vec.push_back(i); printf("%d\n", vec.size()); for(int i = 0; i < vec.size(); i++) printf("%d%c", vec[i], " \n"[i + 1 == vec.size()]); return 0;}
D - Olya and Energy Drinks (bfs)
题意:给出一个1000*1000的迷宫,然后给出初始点和终点,然后每次能沿着上下左右其中一个方向移动最多k步。问最少需要几步走到终点。
思路:
直接bfs显然会超时。容易得到状态一共有
剪枝呢就是,考虑到每次抵达点(x,y)的时候,如果(x,y,dir)已经访问过了,显然可以break。
#include <bits/stdc++.h>using namespace std;const int maxn = 1000 + 5;const int INF = 0x3f3f3f3f;char ma[maxn][maxn];int dp[maxn][maxn];bool vis[maxn][maxn][4];int n, m, k, sx, sy, gx, gy;int dx[] = {0, 0, 1, -1};int dy[] = {1, -1, 0, 0};int bfs(){ memset(dp, INF, sizeof(dp)); memset(vis, 0, sizeof(vis)); queue<pair<int, int>>que; que.push({sx, sy}); dp[sx][sy] = 0; for(int i = 0; i < 4; i++) vis[sx][sy][i] = 1; while(que.size()) { pair<int, int> cur = que.front();que.pop(); if(cur.first == gx && cur.second == gy) return dp[cur.first][cur.second]; for(int i = 0; i < 4; i++) { int step = 1; while(step <= k) { int fx = cur.first + dx[i] * step; int fy = cur.second + dy[i] * step; if(!(1 <= fx && fx <= n && 1 <= fy && fy <= m && ma[fx][fy] == '.' && vis[fx][fy][i] == 0)) break; if(dp[cur.first][cur.second] + 1 > dp[fx][fy]) break; vis[fx][fy][i] = 1; dp[fx][fy] = dp[cur.first][cur.second] + 1; que.push({fx, fy}); step++; } } } return -1;}int main(){ scanf("%d%d%d", &n, &m, &k); for(int i = 1; i <= n; i++) scanf("%s", ma[i] + 1); scanf("%d%d%d%d", &sx, &sy, &gx, &gy); printf("%d\n", bfs()); return 0;}
E - Danil and a Part-time Job (dfs序+线段树)
题意:给出一棵n个结点树,然后每个点开关灯的状态。然后给出q次操作,操作1:统计子树x内的开灯的结点数量,操作2:把字数内的所有开关的状态翻转。
n,q≤100000
思路:
dfs序一下,可以发现是一个区间和的查询,和一个区间修改的操作,加个线段树即可。
#include <bits/stdc++.h>using namespace std;const int maxv = 200000 + 5;vector<int>G[maxv];int a[maxv], b[maxv], in[maxv], out[maxv];int tim;void dfs(int cur, int fa){ in[cur] = ++tim; b[tim] = a[cur]; for(auto o : G[cur]) if(o != fa) { dfs(o, cur); } out[cur] = tim;}const int maxn = maxv << 2 + 5;int tree[maxn], lazy[maxn];#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1void pushup(int rt){tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];}void build(int l, int r, int rt){ if(l == r) { tree[rt] = b[l]; return ; } int mid = (l + r) / 2; build(lson); build(rson); pushup(rt);}void pushdown(int l, int r, int rt){ if(lazy[rt]) { int mid = (l + r) / 2; tree[rt << 1] = (mid - l + 1) - tree[rt << 1]; tree[rt << 1 | 1] = (r - (mid + 1) + 1) - tree[rt << 1 | 1]; lazy[rt << 1] ^= 1; lazy[rt << 1 | 1] ^= 1; lazy[rt] = 0; }}int query(int ql, int qr, int l, int r, int rt){ if(ql <= l && r <= qr) return tree[rt]; pushdown(l, r, rt); int ret = 0, mid = (l + r) / 2; if(ql <= mid) ret += query(ql, qr, lson); if(qr > mid) ret += query(ql, qr, rson); return ret;}void update(int ql, int qr, int l, int r, int rt){ if(ql <= l && r <= qr) { tree[rt] = (r - l + 1) - tree[rt]; lazy[rt] ^= 1; return ; } pushdown(l, r, rt); int mid = (l + r) / 2; if(ql <= mid) update(ql, qr, lson); if(qr > mid) update(ql, qr, rson); pushup(rt);}int main(){ int n; scanf("%d", &n); for(int i = 2, x; i <= n; i++) { scanf("%d", &x); G[x].push_back(i); } for(int i = 1; i <= n; i++) scanf("%d", &a[i]); tim = 0; dfs(1, -1); build(1, n, 1); int q; scanf("%d\n", &q); while(q--) { char cmd[10]; int id; scanf("%s %d", cmd, &id); if(cmd[0] == 'g') {//get printf("%d\n", query(in[id], out[id], 1, n, 1)); } else {//swith update(in[id], out[id], 1, n, 1); } } return 0;}
F - Ann and Books (莫队算法)
题意:详见原题?
思路:
显然我们是可以采用莫队来解决。用一个前缀和来维护一下的话,就转变成在区间[l,r]内,x<=y且a[y] = a[x-1] + k的数对(x,y)有几个。
我们考虑[l,r] -> [l,r+1],此时,a[r + 1]这个数出现的次数++,对答案的贡献度应该是a[r + 1]-k这个数出现的次数。
我们考虑[l,r] -> [l - 1,r+1],此时,a[l-1]这个数出现的次数++,对答案的贡献度应该是a[l - 1]+k这个数出现的次数。
[l,r] -> [l + 1,r]和[l,r - 1]亦是同理。所以我们可以发现我们需要维护一个val出现的次数即可。然后处理完以上,还要处理一个x=l-1的特殊情况。
然后因为数据范围很大的原因,所以需要一个离散化。离散化有蛮多的小细节需要注意。
以上。
#include <bits/stdc++.h>using namespace std;const int maxn = 100000 + 5;int ty[maxn], qian[maxn], hou[maxn];long long tong[maxn], a[maxn], ans[maxn];int cnt = 0;long long kind;struct node{int l, r, block, id;}q[maxn];void erase1(int p){ tong[a[p]]--; if(hou[a[p]]) kind -= tong[hou[a[p]]];}inline void erase2(int p){ tong[a[p]]--; if(qian[a[p]]) kind -= tong[qian[a[p]]];}inline void insert1(int p){ if(hou[a[p]]) kind += tong[hou[a[p]]]; tong[a[p]]++;}inline void insert2(int p){ if(qian[a[p]]) kind += tong[qian[a[p]]]; tong[a[p]]++;}vector<long long>vec;map<long long, int>ma;int main(){ int n, k; scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) scanf("%d", &ty[i]); for(int i = 1; i <= n; i++) { scanf("%lld", &a[i]); a[i] = a[i] * (ty[i] == 1 ? 1 : -1) + a[i - 1]; vec.push_back(a[i]); } sort(vec.begin(), vec.end()); vec.resize(unique(vec.begin(), vec.end()) - vec.begin()); for(auto o : vec) ma[o] = ++cnt; for(int i = 1; i <= n; i++) { int idx = ma[a[i]]; qian[ma[a[i]]] = ma[a[i]-k]; hou[ma[a[i]]] = ma[a[i]+k]; a[i] = idx; } hou[0] = ma[k]; int m, len = sqrt(n); scanf("%d", &m); for(int i = 1; i <= m; i++) { int l, r; scanf("%d%d", &l, &r); q[i] = {l, r, l / len, i}; } sort(q + 1, q + m + 1, [](node &x, node &y) { return x.block < y.block || (x.block == y.block && x.r < y.r); }); int lb = q[1].l, rb = q[1].l - 1; for(int i = 1; i <= m; i++) { while(lb>q[i].l) insert1(--lb); while(rb<q[i].r) insert2(++rb); while(lb<q[i].l) erase1(lb++); while(rb>q[i].r) erase2(rb--); ans[q[i].id] = kind + tong[hou[a[lb-1]]]; } for(int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return 0;}
- Codeforces Round #442 (Div. 2)【solved : 6 / 6】
- Codeforces Round #427 (Div. 2)【solved:4 / 6】
- Codeforces Round #434 (Div. 2)【solved : 4 / 6】
- Codeforces Beta Round #6 (Div. 2 Only)
- Codeforces Beta Round #6 (Div. 2 Only)
- Codeforces Beta Round #6 (Div. 2 Only)
- Codeforces Round #442 (Div. 2)
- Codeforces Round #442 (Div. 2)
- Codeforces Round #442 (Div. 2)
- Educational Codeforces Round 32【solved: 6 / 7】(F待补)
- Codeforces Round #442 (Div. 2) A B
- Codeforces Round #442 (Div. 2) 总结
- Codeforces Round #442 (Div. 2) ABCDE
- Codeforces Round #442 (Div. 2) B
- Codeforces Round #442 (Div. 2) C
- Codeforces Round #442 (Div. 2) P
- Codeforces Round #442 (Div. 2) 解题报告
- Codeforces Round #442 (Div. 2) 877 F
- 接口实现模拟器
- python defacultdict
- 20171026-大胆,再大胆些
- servlet如何判断是哪个表单传来的数据???
- Centos配置ssh免密码互信登录
- Codeforces Round #442 (Div. 2)【solved : 6 / 6】
- selenium自动化(一)
- 基于GitHub搭建Hexo静态博客
- 代码实现input的value值选中HTMLInputElement.setSelectionRange()
- 字典序全排列
- JavaScript原型——构造函数
- 1014. 福尔摩斯的约会 (20)
- Node.js 异常处理
- 【Unity】基于矩阵的UGUI引导蒙版方案