2018 BIT 迎新赛

啊这......总之就是先摸一摸以前的迎新赛,找找手感。

网址http://codeforces.com/gym/102426

A,忘了线性相关是啥,百度一波,然后根据以前的经验,大概高斯消元一波就行了吧。

先消成倒三角,然后找一找有没有全0向量。有全零就代表线性相关。

第一次交的时候莫名其妙的WA了...然后微调了几个地方莫名其妙就A了,太怪了。

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 
 5 const int N = 15;
 6 const double eps = 1e-10;
 7 
 8 int n, m;
 9 double a[N][N];
10 
11 inline double fabs(double x) {
12     return (x < 0) ? (-x) : x;
13 }
14 
15 inline bool work() {
16     for(int i = 1; i < n; i++) {
17         for(int j = i; j <= n; j++) {
18             if(fabs(a[j][i]) > eps) {
19                 // [j][i] != 0
20                 std::swap(a[j], a[i]);
21                 break;
22             }
23         }
24         if(fabs(a[i][i]) < eps) {
25             continue;
26         }
27         for(int j = i + 1; j <= n; j++) {
28             if(fabs(a[j][i]) < eps) {
29                 continue;
30             }
31             double x = a[j][i] / a[i][i];
32             for(int k = i; k <= m; k++) {
33                 a[j][k] -= a[i][k] * x;
34             }
35         }
36     }
37     for(int i = 1; i <= n; i++) {
38         bool flag = false;
39         for(int j = 1; j <= m; j++) {
40             if(fabs(a[i][j]) > eps) {
41                 flag = true;
42                 break;
43             }
44         }
45         if(!flag) {
46             return true;
47         }
48     }
49     return false;
50 }
51 
52 inline void solve() {
53 
54     memset(a, 0, sizeof(a));
55     scanf("%d%d", &n, &m);
56     for(int i = 1; i <= n; i++) {
57         for(int j = 1; j <= m; j++) {
58             int x;
59             scanf("%d", &x);
60             a[i][j] = x;
61         }
62     }
63 
64     if(work()) {
65         printf("YES\n");
66     }
67     else {
68         printf("NO\n");
69     }
70 
71     return;
72 }
73 
74 int main() {
75 
76     int T;
77     scanf("%d", &T);
78     while(T--) {
79         solve();
80     }
81 
82     return 0;
83 }
AC代码

B,仔细一看,傻逼打表题,1s不到就跑出来答案了。

答案是93389411

C,有点复杂,没啥技术含量,不想写先放着。

D,cnm傻逼才会去写啊!

E,啊这,一开始看到的时候,觉得蓝书上面应该见过类似的,结果不会做。想了半天,最后还是回到了二分上,想到我有没有办法先二分到哪个位置开头,再二分那一个串,结果就想到了从外部二分答案,啊这!秒切了。log²能过。

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 const int N = 100010;
 5 
 6 LL a[N];
 7 int n;
 8 
 9 template <typename T>
10 inline T max(const T &a, const T &b) {
11     return a > b ? a : b;
12 }
13 template <typename T>
14 inline T min(const T &a, const T &b) {
15     return a > b ? b : a;
16 }
17 
18 inline LL cnt(LL x) {
19     LL ans = 0;
20     for(int i = 1; i <= n; i++) {
21         int l = i, r = n, mid;
22         while(l < r) {
23             mid = (l + r + 1) >> 1;
24             if(a[mid] - a[i - 1] < x) {
25                 l = mid;
26             }
27             else {
28                 r = mid - 1;
29             }
30         }
31         ans += r - i + 1;
32     }
33     return ans;
34 }
35 
36 int main() {
37     LL l = 0x7fffffffffffffffll, r, mid, k;
38     scanf("%d%lld", &n, &k);
39     for(int i = 1; i <= n; i++) {
40         scanf("%lld", &a[i]);
41         l = min(l, a[i]);
42         a[i] += a[i - 1];
43     }
44     r = a[n];
45     while(l < r) {
46         mid = (l + r + 1) >> 1;
47         if(cnt(mid) >= k) {
48             r = mid - 1;
49         }
50         else {
51             l = mid;
52         }
53     }
54     printf("%lld\n", r);
55     return 0;
56 }
AC代码

写了半天,二分写法快忘了...

F,好!见到一个水题,爽!

直接把n * m个数排序,就是个阶梯状的东西,然后随便做做就行了。

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 const int N = 1e6 + 10;
 5 
 6 int n, m, t, v, a[N], b[N];
 7 
 8 int main() {
 9     scanf("%d%d%d", &n, &m, &v);
10     t = n * m;
11     for(int i = 1; i <= n; i++) {
12         for(int j = 1; j <= m; j++) {
13             scanf("%d", &a[(i - 1) * m + j]);
14         }
15     }
16     std::sort(a + 1, a + t + 1);
17     int h = a[t];
18     for(int i = 1; i <= t; i++) {
19         b[i] = a[i] - a[i - 1];
20     }
21     for(int i = t; i >= 1 && v; i--) {
22         if(v >= b[i] * (t - i + 1)) {
23             v -= b[i] * (t - i + 1);
24             h -= b[i];
25         }
26         else {
27             h -= v / (t - i + 1);
28         }
29     }
30     printf("%d\n", h);
31     return 0;
32 }
AC代码

G,好!位运算水题,秒了。

 1 #include <bits/stdc++.h>
 2 
 3 const int N = 20;
 4 
 5 int a[N], n = 11;
 6 char str[N];
 7 
 8 inline void out() {
 9     for(int i = 0; i < n; i++) {
10         printf("%d ", a[i]);
11     }
12     puts("");
13     return;
14 }
15 
16 inline void add(int x) {
17     for(int i = 0; i < n; i++) {
18         if(x & (1 << i)) {
19             a[i]++;
20         }
21     }
22     out();
23     return;
24 }
25 
26 inline void del(int x) {
27     int i = 0;
28     while((1 << i) < x) {
29         ++i;
30     }
31     while(!a[i] && i < n) {
32         ++i;
33     }
34     if(i == n) {
35         printf("ERROR!\n");
36     }
37     else {
38         int y = 1 << i;
39         a[i]--;
40         add(y - x);
41     }
42     return;
43 }
44 
45 int main() {
46     int T;
47     scanf("%d", &T);
48     while(T--) {
49         int x;
50         scanf("%s%d", str, &x);
51         if(str[0] == 'f') {
52             add(x);
53         }
54         else {
55             del(x);
56         }
57     }
58     return 0;
59 }
AC代码

H

先想到,如果子区间白学那么父区间也白学。然后考虑预处理出对于左端点 i ,到ans[i]是最小的白学区间。

考虑到ans[i] ≤ ans[i + 1],可以从右向左加数字,同时用一个ans[i]指针从右向左单调移动。又考虑到ans[i]一定是三角形的一边,于是把那个指针从右向左移动,用一个值域数据结构来维护......挂了。到这里,不会做了。

第二天,发现非白学串长度不会超过64,因为从最小往大加入,每次加入一个新数,如果想要不形成白学串,就要大于最大的两个之和。(感觉不是很严谨...)有了这个性质之后,直接从每个位置开始找log个,就是个log²了(还是用值域数据结构来维护有哪些数),为了速度我们选择树状数组,抱着试一试的心态写出来,结果切了。

更具体的说,我们枚举左端点再枚举右端点,且这两个数一定是三角形的两边。于是第三条边就是(abs(a - b), a + b)这个范围内的了。

 1 #include <bits/stdc++.h>
 2 
 3 const int N = 100010;
 4 
 5 int a[N], n, ans[N], X[N], top, ta[N * 2];
 6 
 7 inline int abs(int x) {
 8     return (x < 0) ? (-x) : x;
 9 }
10 
11 inline void add(int i, int x) {
12     for(; i <= top; i += i & (-i)) {
13         ta[i] += x;
14     }
15 }
16 inline int ask(int i) {
17     int ans = 0;
18     for(; i; i -= i & (-i)) {
19         ans += ta[i];
20     }
21     return ans;
22 }
23 inline int ask(int l, int r) {
24     if(l > r) return 0;
25     return ask(r) - ask(l - 1);
26 }
27 
28 inline void Main() {
29     int m;
30     scanf("%d%d", &n, &m);
31     ans[n + 1] = n + 1;
32     for(int i = 1; i <= n; i++) {
33         scanf("%d", &a[i]);
34         X[i] = a[i];
35     }
36     std::sort(X + 1, X + n + 1);
37     top = std::unique(X + 1, X + n + 1) - X - 1;
38     for(int i = 1; i <= n; i++) {
39         a[i] = std::lower_bound(X + 1, X + top + 1, a[i]) - X;
40     }
41     // solve
42     for(int i = n; i >= 1; i--) {
43         ans[i] = n + 1;
44         for(int j = i + 1; j <= n; j++) {
45             int l = abs(X[a[i]] - X[a[j]]), r = X[a[i]] + X[a[j]];
46             l = std::upper_bound(X + 1, X + top + 1, l) - X;
47             r = std::lower_bound(X + 1, X + top + 1, r) - X - 1;
48             if(ask(l, r)) {
49                 ans[i] = j;
50                 break;
51             }
52             if(j == ans[i + 1]) {
53                 ans[i] = j;
54                 break;
55             }
56             add(a[j], 1);
57         }
58         for(int j = i + 1; j < ans[i]; j++) {
59             add(a[j], -1);
60         }
61     }
62 
63     int l, r;
64     for(int i = 1; i <= m; i++) {
65         scanf("%d%d", &l, &r);
66         if(r >= ans[l]) {
67             printf("yes\n");
68         }
69         else {
70             printf("no\n");
71         }
72     }
73     return;
74 }
75 
76 int main() {
77     int T;
78     scanf("%d", &T);
79     while(T--) {
80         Main();
81     }
82     return 0;
83 }
AC代码

I,搞不倒

J,通过人数是最多的,然而...被long long坑了一次。

仔细一研究,发现是个树形结构,一个树形DP就搞定了。

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 const int N = 200010;
 5 
 6 struct Edge {
 7     int nex, v;
 8 }edge[N]; int tp;
 9 
10 int e[N], fa[N], n;
11 LL f[N][2];
12 
13 inline void adde(int x, int y) {
14     edge[++tp].v = y;
15     edge[tp].nex = e[x];
16     e[x] = tp;
17 }
18 
19 void dfs(int x) {
20     for(int i = e[x]; i; i = edge[i].nex) {
21         int y = edge[i].v;
22         dfs(y);
23         f[x][0] += std::max(f[y][0], f[y][1]);
24         f[x][1] += f[y][0];
25     }
26     f[x][1] += x;
27     return;
28 }
29 
30 int main() {
31     scanf("%d", &n);
32     for(int i = 1; i <= n; i++) {
33         if(i & 1) {
34             adde(n + 1, i);
35         }
36         else {
37             adde(i / 2, i);
38         }
39     }
40     dfs(n + 1);
41     f[n + 1][1] -= n + 1;
42     printf("%lld\n", std::max(f[n + 1][0], f[n + 1][1]));
43     return 0;
44 }
AC代码

K,10个窗口,10次点击,瞧不起谁呢……

posted @ 2020-09-27 20:11  huyufeifei  阅读(117)  评论(0编辑  收藏