A Water The Garden
没啥好说的。
B Tea Queue
没啥好说的。
C Swap Adjacent Elements
题意大概就是给一个置换,有一些位置上是可以交换的,问能不能换成一个1 2 3 4 5...这样的置换。
好坑啊,一开始猜了个结论,以为对逆序产生贡献的地方有1就可以了。
5
1 5 2 3 4
0100
这一组就gg了。
实际上把连续出现1的那一部份都排个序,最后再check一下,复杂度想想是可以的。

1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int N = 200005;
5
6 int n, a[N];
7 char s[N];
8 int main() {
9 scanf("%d", &n);
10 for (int i = 0; i < n; ++i) scanf("%d", a + i);
11 scanf("%s", s);
12 s[n - 1] = '0';
13
14 int l, r;
15 l = r = -1;
16 for (int i = 0; i < n; ++i) {
17 int k = s[i] - '0';
18 if (k) {
19 if (l != -1) r++;
20 else l = r = i;
21 } else {
22 if (l >= 0 && r >= 0) sort(a + l, a + r + 1 + 1);
23 l = r = -1;
24 }
25 }
26 bool flag = 1;
27 for (int i = 1; i < n; ++i) {
28 if (a[i] < a[i - 1]) {
29 flag = 0; break;
30 }
31 }
32 printf("%s", flag ? "YES" : "NO");
33 }
D Tanks
没补。
E Connected Components?
题意大概是给你一个补图,问原图有多少个联通块,每个联通块里有几个结点。
有点类似于HDU5876。
不过这个题只要求联通块,那么每个点最多就被访问一次,存图还是得存补图的,用一个set或链表来维护当前有哪些点没有被访问过,BFS每次从这些没有被访问过的点里走原图中有边的点。
其实就是判断一下补图中是不是有边,补图中有边,那么原图就是没边的。

1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int N = 2e5 + 7;
5
6 int n, m;
7 unordered_set<int> g[N];
8 int vis[N];
9 set<int> unused;
10 int main() {
11 scanf("%d %d", &n, &m);
12 for (int i = 0; i < m; ++i) {
13 int x, y;
14 scanf("%d %d", &x, &y);
15 g[x].insert(y);
16 g[y].insert(x);
17 }
18 for (int i = 1; i <= n; ++i) {
19 unused.insert(i);
20 }
21
22 vector<int> ans;
23 for (int i = 1; i <= n; ++i) {
24 if (!vis[i]) {
25 int cnt = 0;
26 queue<int> Q;
27 Q.push(i); unused.erase(i);
28
29 while (!Q.empty()) {
30 int u = Q.front();
31 Q.pop();
32 ++cnt;
33 vis[u] = true;
34 vector<int> del;
35 for (int v : unused) {
36 if (g[u].find(v) != g[u].end()) continue;
37 del.push_back(v);
38 Q.push(v);
39 }
40 for (int j : del) unused.erase(j);
41 }
42 ans.push_back(cnt);
43 }
44 }
45
46 sort(ans.begin(), ans.end());
47 printf("%d\n", ans.size());
48 for (int i : ans) printf("%d ", i);
49 printf("\n");
50 }
F SUM and REPLACE
题意大概是有一个序列,每次操作一段区间,把这段区间里的每一个数都变成这个数的因子个数/查询这个区间的和。
有一个很好的性质就是,当这个数变成1或者2的时候这个数就不会变了。
线段树单点更新,区间查询咯。
那么搞搞就行了,因子也$sqrt(n)$的搞搞就好了,但是要维护一个区间最大值,当区间最大值 <= 2的时候就不需要搞下去了。

1 #include <bits/stdc++.h>
2 using namespace std;
3
4 typedef long long ll;
5 #define lson o<<1
6 #define rson o<<1|1
7 const int N = 300030;
8 const int X = 1000001;
9
10 int n, m;
11 int a[N], d[X];
12 struct node {
13 int l, r;
14 ll sum, max;
15 } st[N << 2];
16
17 void init() {
18 for (int i = 1; i < X; ++i)
19 for (int j = i; j < X; j += i) d[j]++;
20 }
21
22 void push_up(int o) {
23 st[o].sum = st[lson].sum + st[rson].sum;
24 st[o].max = max(st[lson].max, st[rson].max);
25 }
26
27 void build(int l = 1, int r = n, int o = 1) {
28 st[o].l = l; st[o].r = r; st[o].sum = st[o].max = 0;
29 if (l == r) {
30 st[o].sum = st[o].max = a[l];
31 return;
32 }
33 int mid = (l + r) / 2;
34 build(l, mid, lson);
35 build(mid + 1, r, rson);
36 push_up(o);
37 }
38
39 void advance(int l, int r, int o = 1) {
40 if (st[o].r < l or st[o].l > r or st[o].max <= 2) return;
41 if (st[o].l == st[o].r) {
42 st[o].sum = st[o].max = d[st[o].sum];
43 return;
44 }
45 advance(l, r, lson);
46 advance(l, r, rson);
47 push_up(o);
48 }
49
50 ll query(int l, int r, int o = 1) {
51 if (st[o].r < l or st[o].l > r) return 0;
52 if (l <= st[o].l and st[o].r <= r) return st[o].sum;
53 return query(l, r, lson) + query(l, r, rson);
54 }
55
56 int main() {
57 init();
58 scanf("%d %d", &n, &m);
59 for (int i = 1; i <= n; ++i) scanf("%d", a + i);
60 build();
61 for (int i = 0; i < m; ++i) {
62 static int l, r, t;
63 scanf("%d %d %d", &t, &l, &r);
64 if (t == 1) {
65 advance(l, r);
66 } else {
67 printf("%lld\n", query(l, r));
68 }
69 }
70 }
G List Of Integers
题意大概就是要求比x大的与p互质的第k个数。
没想到可以二分答案,那么问题就成了一个判定问题。
先搞出$[1, x]$中与p互质的数有几个(假设t个),再二分一下答案ans,判断一下$[1,ans]$中是不是大于等于t+k个,二分这个下界就是了。
算互质数个数的话,比较经典的问题,可以用容斥搞出与p不互质的数个数,减一减就好。

1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int N = 1e6 + 20;
5
6 vector<int> a[N];
7 vector<int> Q;
8 int t, x, p, k;
9
10 int solve(int n, int p) {
11 int ret = 0;
12 Q.clear();
13 Q.push_back(-1);
14 vector<int> & f = a[p];
15 for (int i = 0; i < (int)f.size(); ++i) {
16 int top = Q.size();
17 for (int j = 0; j < top; ++j) {
18 Q.push_back(-1 * f[i] * Q[j]);
19 }
20 }
21 for (int i = 1; i < (int)Q.size(); ++i) {
22 ret += n / Q[i];
23 }
24 return n - ret;
25 }
26
27 int main() {
28 for (int i = 2; i <= 1000000; ++i) {
29 if (a[i].size() > 0) continue;
30 for (int j = i; j <= 1000000; j += i) {
31 a[j].push_back(i);
32 }
33 }
34
35 scanf("%d", &t);
36 while (t--) {
37 scanf("%d %d %d", &x, &p, &k);
38
39 k += solve(x, p);
40 int lb = 1, ub = 1e9, ans = x;
41 while (lb <= ub) {
42 int mid = (lb + ub) / 2;
43 if (solve(mid, p) >= k) {
44 ans = mid;
45 ub = mid - 1;
46 } else {
47 lb = mid + 1;
48 }
49 }
50 printf("%d\n", ans);
51 }
52 }
来源:https://www.cnblogs.com/wfgu/p/8433539.html
