「题解」The 19th Zhejiang Provincial Collegiate Programming Contest

Before

比赛

清明和一个队友 vp 的,完全的跟榜做题,感觉发挥的还行。

B - JB Loves Comma

签到

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
#include <bits/stdc++.h> std::string s; int main() { std::cin >> s; int n = s.length(); for (int i = 0; i < n; ++i) { putchar(s[i]); if (i >= 2 && s[i] == 'b' && s[i - 1] == 'j' && s[i - 2] == 'c') putchar(','); } return 0; }

C - JB Wants to Earn Big Money

签到

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
#include <bits/stdc++.h> int n, m, x; int main() { scanf("%d %d %d", &n, &m, &x); int ans = 0; for (int i = 1, a; i <= n; ++i) { scanf("%d", &a); if (a >= x) ++ans; } for (int i = 1, a; i <= m; ++i) { scanf("%d", &a); if (a <= x) ++ans; } printf("%d\n", ans); return 0; }

A - JB Loves Math

分类讨论

  • a=b,答案为 0
  • a<b
    • ba 为奇数,答案为 1
    • ba 为偶数,加两次奇数减一次偶数可以完成,还要考虑加偶数次奇数的情况,两者取最小值
  • a>b
    • ab 为奇数,答案为 2
    • ab 为偶数,答案为 1
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
#include <bits/stdc++.h> int T; int min(int x, int y) { return x < y ? x : y; } int main() { scanf("%d", &T); while (T--) { int a, b; scanf("%d %d", &a, &b); if (a == b) puts("0"); else if (a < b) { if ((b - a) & 1) puts("1"); else { int cnt = 1, x = (b - a); while (!(x & 1)) cnt *= 2, x >>= 1; printf("%d\n", min(cnt, 3)); } } else { if ((a - b) & 1) puts("2"); else puts("1"); } } return 0; }

赛时想当然了,罚时了两发。

L - Candy Machine

将糖果按甜度由小到大排序,选择的子集一定是从第一个糖果到某个糖果(为了使平均值尽量小)。

用双指针方法维护有多少糖果甜度大于平均值。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
#include <bits/stdc++.h> #define N 1000001 typedef long long ll; int n, ans, a[N]; int max(int x, int y) { return x > y ? x : y; } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); std::sort(a + 1, a + n + 1); int l = 1, r = 0; ll sum = 0; while (r < n) { ++r; sum += a[r]; double avg = 1.0 * sum / r; while (l <= r && a[l] - avg <= 0) ++l; ans = max(ans, r - l + 1); } printf("%d\n", ans); return 0; }

G - Easy Glide

可以发现有用的点只有几个滑翔点和起点终点,几个点之间互相建边,边长为所需时间(可以通过简单数学计算的出)。然后跑最短路。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
#include <bits/stdc++.h> #define N 1518 #define inf 2147483647 #define fir first #define sec second typedef std::pair<double, int> pdi; bool vis[N]; double dis[N]; int ecnt, head[N]; int n, v1, v2, x[N], y[N]; struct Edge { double w; int nxt, v; }e[N * N]; void add(int u, int v, double w) { e[++ecnt].v = v, e[ecnt].w = w; e[ecnt].nxt = head[u], head[u] = ecnt; } double getd(int x_, int y_ ) { // return abs(x[x_] - x[y_]) + abs(y[x_] - y[y_]); return (double)sqrt(1ll * (x[x_] - x[y_]) * (x[x_] - x[y_]) + 1ll * (y[x_] - y[y_]) * (y[x_] - y[y_])); } void Dij() { for (int i = 1; i <= n + 2; ++i) dis[i] = inf; dis[n + 1] = 0; std::priority_queue<pdi, std::vector<pdi>, std::greater<> > q; q.push({dis[n + 1], n + 1}); while (!q.empty()) { pdi u = q.top(); q.pop(); if (vis[u.sec]) continue; vis[u.sec] = true; for (int i = head[u.sec]; i; i = e[i].nxt) { int v = e[i].v; if (!vis[v] && dis[v] > dis[u.sec] + e[i].w) { dis[v] = dis[u.sec] + e[i].w; q.push({dis[v], v}); } } } } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d %d", &x[i], &y[i]); } scanf("%d %d %d %d", &x[n + 1], &y[n + 1], &x[n + 2], &y[n + 2]); scanf("%d %d", &v1, &v2); add(n + 1, n + 2, 1.0 * getd(n + 1, n + 2) / v1); for (int i = 1; i <= n; ++i) { add(n + 1, i, 1.0 * getd(i, n + 1) / v1); double d = getd(i, n + 2); add(i, n + 2, (d <= v2 * 3) ? (1.0 * d / v2) : (3.0 + 1.0 * (d - v2 * 3.0) / v1)); for (int j = 1; j <= n; ++j) { if (i == j) continue; else { d = getd(i, j); add(i, j, (d <= v2 * 3) ? (1.0 * d / v2) : (3.0 + 1.0 * (d - v2 * 3.0) / v1)); } } } Dij(); printf("%.12lf", dis[n + 2]); return 0; }

算距离炸了 int,队友不相信我的的最短路,罚时了两发。

M - BpbBppbpBB

数满足形状的空白,然后判断空白间的距离来计算数量。队友写的。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
#include<bits/stdc++.h> using namespace std; #define ri int #define MAXN 1010 #define pii pair< int,int > #define fi first #define se second const int dx[]={0,0,0,1,1,1,1,2,2,2,2,3,3}; const int dy[]={0,0,1,-1,0,1,2,-1,0,1,2,0,1}; char s[MAXN]; int a[MAXN][MAXN],n,m; inline bool jud(int x,int y) { if(x-1<1 || x+4>n || y-2<1 || y+3>m) return 0; for(ri i=1;i<=12;i++) if(a[x+dx[i]][y+dy[i]]) return 0; int ret=0; for(ri i=x-1;i<=x+4;i++) for(ri j=y-2;j<=y+3;j++) ret+=(a[i][j]==0); return (ret==12); } int main() { cin>>n>>m; for(ri i=1;i<=n;i++) { scanf("%s",s+1); for(ri j=1;j<=m;j++) { if(s[j]=='#') a[i][j]=1; else a[i][j]=0; } } vector< pii > v; for(ri i=1;i<=n;i++) for(ri j=1;j<=m;j++) if(!a[i][j]) if(jud(i,j)) { v.push_back(make_pair(i,j)); } int ans1=0; for(auto i=v.begin();i!=v.end();++i) { int x1=(*i).fi,y1=(*i).se,x2,y2; for(auto j=i+1;j!=v.end();++j) { x2=(*j).fi,y2=(*j).se; if((x1==x2 && abs(y1-y2)==7) || (y1==y2 && abs(x1-x2)==7)) ++ans1; } } printf("%d %d",ans1,v.size()-ans1*2); }

I - Barbecue

  • 初始为回文串,先手必败
  • 长度为 2 的串,先手必败。
  • 更长的非回文串,判断两边分别删掉一个字符是否为回文,都为回文,先手必败,否则看长度减一的情况。

发现必胜必败很好算。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
#include <bits/stdc++.h> #define N 1000001 int min(int x, int y) { return x < y ? x : y; } int max(int x, int y) { return x > y ? x : y; } std::string s; int n, q, cnt, p[N << 1], ans[N]; char data[N << 1], *res[2] = {"Putata", "Budada"}; void qr() { data[0] = '~', data[cnt = 1] = '|'; for (int i = 0, st = s.length(); i < st; ++i) { data[++cnt] = s[i], data[++cnt] = '|'; } } bool is(int l, int r) { return p[2 * l + (r - l + 1) + 1] >= (r - l + 1); } int main() { scanf("%d %d", &n, &q); std::cin >> s; qr(); for (int t = 1, r = 0, mid = 0; t <= cnt; ++t) { if (t <= r) p[t] = min(p[(mid << 1) - t], r - t + 1); while (data[t - p[t]] == data[t + p[t]]) ++p[t]; if (p[t] + t > r) r = p[t] + t - 1, mid = t; } ans[1] = ans[2] = 1; for (int i = 3; i <= n; ++i) ans[i] = ans[i - 1] ^ 1; for (int i = 1, l, r; i <= q; ++i) { scanf("%d %d", &l, &r); if (r - l + 1 <= 2) puts("Budada"); else { if (is(l - 1, r - 1) || (is(l - 1, r - 2) && is(l, r - 1))) puts("Budada"); else puts(res[ans[r - l + 1]]); } } return 0; }

被队友忽悠写了不熟悉的 manacher,调了好久。

After

昨天和三个队友 vp 了一场。

卡题了,还是简单题,气氛压抑。

唉。多练!希望正式参赛别卡。

posted @   yu__xuan  阅读(117)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开