Educational Round 37 补题记录

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 }
View Code

 

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

转载于:https://www.cnblogs.com/wfgu/p/8433539.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值