Educational Codeforces Round 37 [Codeforces920]
2018-02-04 23:26
309 查看
题目链接
官方题解
①若当前可获得时间time<=rtime<=r,则能在max(l,time)max(l,time)获得茶,下一次可获得茶的时间为time=max(l,time)+1time=max(l,time)+1;
②如当前可获得时间time>rtime>r,则不能获得茶而离开,结果为00。
①将[l,r][l,r]内的所有数变成其因子的个数
②求[l,r][l,r]内所有数的和
但是要注意更新的特殊性,就能发觉每个数减少的很快,最多66次之后就不再变化,所以在更新前,要判断当前线段内的数是否存在可以继续更新的值(只有1和21和2不能进行更新)。而这样对每个点的更新操作最多只有66次,所以可以放心更新。
对于每个点维护两个值:mxmx表示线段内的最大值,用于更新剪枝;sumsum表示线段内所有数的和,用于查询结果。
官方题解
A. Swap Adjacent Elements
题目大意
在长度为nn的草坪上,有kk个水龙头,第ii个水龙头位置为xixi,水龙头的水在打开后第jj秒会对[x-(j-1), x+(j-1)]内的所有草坪洒水。现在同时打开所有水龙头,求最短多少秒时所有草坪都能被洒到水?思路 - 模拟
相邻两个水龙头之间的草坪全部能被洒水需要cur−last2+1cur−last2+1秒,左端点处能在x1x1内将左边的草坪洒上水,又端点出能在n−xk+1n−xk+1内将右边的草坪洒上水,则答案为所有值中的最大值。代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 203; int n, k, ans, last, cur; int main() { int T; scanf("%d", &T); while(T-- > 0) { scanf("%d%d", &n, &k); scanf("%d", &last); ans = last; while(--k > 0) { scanf("%d", &cur); ans = max(ans, ((cur - last) >> 1) + 1); last = cur; } ans = max(ans, n - last + 1); printf("%d\n", ans); } }
B. Tea Queue
题目大意
有nn个人在排队,第ii个人在lili时到达队尾,若在riri时还未在队首,则必须空手离开;队首的人会获得茶,然后在下一秒离开;求每个人端着茶的时间,不存在则为00。思路 - 模拟
模拟每个人入队后的情况:①若当前可获得时间time<=rtime<=r,则能在max(l,time)max(l,time)获得茶,下一次可获得茶的时间为time=max(l,time)+1time=max(l,time)+1;
②如当前可获得时间time>rtime>r,则不能获得茶而离开,结果为00。
代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1003; int n, time; int l, r, ans[MAXN]; int main() { int T; scanf("%d", &T); while(T-- > 0) { scanf("%d", &n); time = 0; for(int i = 1; i <= n; ++i) { scanf("%d%d", &l, &r); if(r >= time) { ans[i] = max(l, time) ; time = ans[i] + 1; } else { ans[i] = 0; } } for(int i = 1; i <= n; ++i) { printf("%d%c", ans[i], i == n ? '\n' : ' '); } } }
C. Swap Adjacent Elements
题目大意
有一个长度为nn的数组,数组内为1 n1 n的一个排列,现有一个操作:交换xixi和xi+1xi+1(无次数限制),在给定长度为n−1n−1的01串01串,00表示数组中相同下标的数不能进行这样的操作;11表示数组中相同下标的数能进行这样的操作。求当前数组能否变成一个递增的数组?思路 - 模拟
很容易就能发现若存在连续为11的区间[l,r][l,r],则[l,r+1][l,r+1]内的数能交换到该区间内的任意以一个位置,所以以00将数组划分为多个区间,若每个区间内的数都是其区间内的一个下标,则最终能变成一个递增的数组。代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 200003; int n, a[MAXN], last; char s[MAXN]; int nxt[MAXN]; bool border; bool judge() { s = '0'; for(int i = n; i >= 1; --i) { if(s[i] == '0') { nxt[i] = i; } else { nxt[i] = nxt[i + 1]; } } border = false; for(int i = 1; i <= n; ++i) { if(a[i] > nxt[i]) { return false; } if(s[i] == '0') { if(!border && a[i] != i) { return false; } border = false; } else { if(a[i] == nxt[i]) { border = true; } } } return true; } int main() { while(1 == scanf("%d", &n)) { for(int i = 1; i <= n; ++i) { scanf("%d", a + i); } scanf("%s", s + 1); printf("%s\n", judge() ? "YES" : "NO"); } }
E. Connected Components?
题目大意
给定nn个的顶点的无向图,以及图中不存在的边,求该无向图的联通分量的个数及每个联通分量的大小?思路 - dfs
很容易就能想到dfsdfs求联通分量,但是由于该无向图是密集图,不能通过遍历边的方式进行搜索,只能通过遍历点的方式进行搜索。所以需要维护未使用的点集(我使用链表实现,并通过并查集思想快速获得下一个未使用的顶点),每次进入dfsdfs时,对于当前顶点uu,遍历未使用的点vv,如果uu到vv存在边,则移除点vv,递归即可。代码
#include <cstdio> #include <cstring> #include <set> #include <algorithm> using namespace std; const int MAXN = 200003; int n, m, cnt; int ans[MAXN]; set<int> edge[MAXN]; int nxt[MAXN]; bool vis[MAXN]; int getNxt(int cur) { if(vis[nxt[cur]]) { nxt[cur] = getNxt(nxt[cur]); } return nxt[cur]; } int dfs(int u) { int res = 0, v; for(v = getNxt(0); v <= n; v = getNxt(v)) { if(edge[u].find(v) == edge[u].end()) { vis[v] = true; res += dfs(v) + 1; } } return res; } int main() { int u, v; while(2 == scanf("%d%d", &n, &m)) { vis[n + 1] = false; nxt[0] = 1; for(int i = 1; i <= n; ++i) { edge[i].clear(); vis[i] = false; nxt[i] = i + 1; } while(m-- > 0) { scanf("%d%d", &u, &v); edge[u].insert(v); edge[v].insert(u); } cnt = 0; for(v = getNxt(0); v <= n; v = getNxt(v)) { vis[v] = true; ans[cnt++] = dfs(v) + 1; } sort(ans, ans + cnt); printf("%d\n", cnt); for(int i = 0; i < cnt; ++i) { printf("%d%c", ans[i], i == cnt - 1 ? '\n' : ' '); } } }
F. SUM and REPLACE
题目大意
给定长度为nn的数组,有两个操作:①将[l,r][l,r]内的所有数变成其因子的个数
②求[l,r][l,r]内所有数的和
思路 - 线段树
看到区间更新和查询,很容易就能想到线段树。但是要注意更新的特殊性,就能发觉每个数减少的很快,最多66次之后就不再变化,所以在更新前,要判断当前线段内的数是否存在可以继续更新的值(只有1和21和2不能进行更新)。而这样对每个点的更新操作最多只有66次,所以可以放心更新。
对于每个点维护两个值:mxmx表示线段内的最大值,用于更新剪枝;sumsum表示线段内所有数的和,用于查询结果。
代码
#include <cstdio> #include <cstring> #include <algorithm> #define lson (i << 1) #define rson ((i << 1) | 1) using namespace std; const int MAXN = 300003; const int MAX_VALUE = 1000003; int d[MAX_VALUE], L, R; struct Node { int l, r; int mx; long long sum; }tr[MAXN << 2]; void build(int i, int l, int r) { tr[i].l = l; tr[i].r = r; if(l == r) { scanf("%d", &tr[i].mx); tr[i].sum = tr[i].mx; return ; } int mid = (l + r) >> 1; build(lson, l , mid); build(rson, mid + 1, r); tr[i].mx = max(tr[lson].mx, tr[rson].mx); tr[i].sum = tr[lson].sum + tr[rson].sum; } void update(int i) { if(tr[i].l == tr[i].r) { tr[i].sum = tr[i].mx = d[tr[i].mx]; return ; } if(L <= tr[lson].r && tr[lson].mx > 2) { update(lson); } if(tr[rson].l <= R && tr[rson].mx > 2) { update(rson); } tr[i].mx = max(tr[lson].mx, tr[rson].mx); tr[i].sum = tr[lson].sum + tr[rson].sum; } long long query(int i) { if(L <= tr[i].l && tr[i].r <= R) { return tr[i].sum; } long long ans = 0; if(L <= tr[lson].r) { ans += query(lson); } if(tr[rson].l <= R) { ans += query(rson); } return ans; } void init() { memset(d, 0, sizeof(d)); for(int i = 1; i < MAX_VALUE; ++i) { for(int j = i; j < MAX_VALUE; j += i) { ++d[j]; } } } int n, m; int type; int main() { init(); while(2 == scanf("%d%d", &n, &m)) { build(1, 1, n); while(m-- > 0) { scanf("%d%d%d", &type, &L, &R); if(type == 1) { update(1); } else { printf("%I64d\n", query(1)); } } } }
相关文章推荐
- 【Educational Codeforces Round 37 E】Connected Components?
- Codeforces Educational Codeforces Round 37 E
- Educational Codeforces Round 37 (Rated for Div. 2) E. Congruence Equation
- Educational Codeforces Round 37 (Rated for Div. 2) E. Connected Components?(连通分量的个数,STL)
- Educational Codeforces Round 37 (Rated for Div. 2) 920E E. Connected Components?
- Educational Codeforces Round 37 (Rated for Div. 2)(A、B、C)
- Educational Codeforces Round 37 (Rated for Div. 2) 【F】【线段树】
- Wannafly挑战赛9+Educational Codeforces Round 37 (Rated for Div. 2)
- Educational Codeforces Round 37 (Rated for Div. 2)
- Educational Codeforces Round 37 (Rated for Div. 2)
- Educational Codeforces Round 37 (Rated for Div. 2)-F-SUM and REPLACE(线段树)
- Educational Codeforces Round 37 E. Connected Components?(bfs)
- [Codeforces]Educational Codeforces Round 37 (Rated for Div. 2)
- 【Educational Codeforces Round 37 F】SUM and REPLACE
- Educational Codeforces Round 37 (Rated for Div. 2) F. SUM and REPLACE(线段树,区间更新)
- Educational Codeforces Round 37 E. Connected Components?(920E)
- Educational Codeforces Round 37-F.SUM and REPLACE题解
- Educational Codeforces Round 37 (Rated for Div. 2) C. Swap Adjacent Elements
- 【CodeForces】Educational Codeforces Round 37 题解
- Educational Codeforces Round 37 (Rated for Div. 2)【A B C】【水】【模拟】