啊这......总之就是先摸一摸以前的迎新赛,找找手感。
网址http://codeforces.com/gym/102426
A,忘了线性相关是啥,百度一波,然后根据以前的经验,大概高斯消元一波就行了吧。
先消成倒三角,然后找一找有没有全0向量。有全零就代表线性相关。
第一次交的时候莫名其妙的WA了...然后微调了几个地方莫名其妙就A了,太怪了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 "); 66 } 67 else { 68 printf("NO "); 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 }
B,仔细一看,傻逼打表题,1s不到就跑出来答案了。
答案是93389411
C,有点复杂,没啥技术含量,不想写先放着。
D,cnm傻逼才会去写啊!
E,啊这,一开始看到的时候,觉得蓝书上面应该见过类似的,结果不会做。想了半天,最后还是回到了二分上,想到我有没有办法先二分到哪个位置开头,再二分那一个串,结果就想到了从外部二分答案,啊这!秒切了。log²能过。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ", r); 55 return 0; 56 }
写了半天,二分写法快忘了...
F,好!见到一个水题,爽!
直接把n * m个数排序,就是个阶梯状的东西,然后随便做做就行了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ", h); 31 return 0; 32 }
G,好!位运算水题,秒了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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! "); 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 }
H
先想到,如果子区间白学那么父区间也白学。然后考虑预处理出对于左端点 i ,到ans[i]是最小的白学区间。
考虑到ans[i] ≤ ans[i + 1],可以从右向左加数字,同时用一个ans[i]指针从右向左单调移动。又考虑到ans[i]一定是三角形的一边,于是把那个指针从右向左移动,用一个值域数据结构来维护......挂了。到这里,不会做了。
第二天,发现非白学串长度不会超过64,因为从最小往大加入,每次加入一个新数,如果想要不形成白学串,就要大于最大的两个之和。(感觉不是很严谨...)有了这个性质之后,直接从每个位置开始找log个,就是个log²了(还是用值域数据结构来维护有哪些数),为了速度我们选择树状数组,抱着试一试的心态写出来,结果切了。
更具体的说,我们枚举左端点再枚举右端点,且这两个数一定是三角形的两边。于是第三条边就是(abs(a - b), a + b)这个范围内的了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 "); 68 } 69 else { 70 printf("no "); 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 }
I,搞不倒
J,通过人数是最多的,然而...被long long坑了一次。
仔细一研究,发现是个树形结构,一个树形DP就搞定了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ", std::max(f[n + 1][0], f[n + 1][1])); 43 return 0; 44 }
K,10个窗口,10次点击,瞧不起谁呢……