2021 CCPC 桂林站总结

一些废话:
最近疫情防控挺严啊,又全都是线上赛了
4月那场EC-final也许真的就是我最后一次线下赛了吧
用的PTA,之前也用过,感觉还算比较友好(虽然比不上牛客

热身赛

测了下环境,大概了解了下配置如何。还挺正常
热身赛3道题,T1签到;T2是一个博弈,要发现一个性质;T3是二分答案trie,也要发现一个性质(虽然最后口胡了个做法没写完)
要是思维上少走点弯路就好了
不多说了,明天加油


正式赛

最终6题首,Ag第二位。
2021 CCPC 桂林站总结_第1张图片

我们前 1.5h 连续过了 A, I, G, E, D,全是1A,当时排名直接上升到 rk3。
然而后期就种种不顺。

B 题其实我们很快也想到了思路,然而在好几个细节上出了问题,调了半天,WA了4发。过B题时我们还在rk12,然而后面rk狂掉。

简要题解

A

签到

D

题意:给定排列A和B,每次可交换A的一个逆序对,构造方案得到B
思路:从大到小考虑,每次把该放的数归位。可以发现只能一路右移,且每次和区间最大值交换是最优的(因为该状态可归约到和非最大值交换后的结果)

E

题意:A买一些边,B从中依次删除DAG,B要次数最小,A要次数最大,求次数
思路:求最小环和最小边。最小环可以每个点跑dijkstra求两两之间最短路获得。

G

题意:给定01串,每次一个1可以向左或右扩展1下(如果有空间),问最少何时塞满
思路:二分答案+贪心

I

题意: 1 ∼ n 1\sim n 1n 元集划分,每个元素有标0或1,求划分后各集合标1次大元素和的最大值

思路:从大到小贪心匹配

B

题意: n n n​ 位加法竖式,每次修改加数一个位,问竖式修改了多少位

思路:用一个set维护和,相同的0和9合并成一项。细节

  • 修改前要拆分0和9
  • 需要考虑进位和退位操作,统计修改位数
  • 修改后要合并0和9

尝试搞,未搞出的题

F

计算几何

关键问题是求线和凸多边形的交点

最后PE,可能被卡精度了,没有注意范围可能到1e18

J

SA/SAM

细节有点多

最后队友差了3min,没调出来

K

比赛时想到了,感觉不太靠谱。要是没有别的题写就试试看了

当时推出状态数是3^15*4,然后,,就没有去尝试,因为感觉不够靠谱

其实是够的,草(可能当时也没想太清楚吧)

(就算没推出状态数,勇一点上去试试说不定都过了)

L

想出了一个 O ( n 3 log ⁡ n + q n log ⁡ n ) O(n^3\log n+qn\log n) O(n3logn+qnlogn)​ 的做法,但好像略超空间上限。而且榜上没人过(THU最后一分钟过了),就放弃了

总结

FJK都挺遗憾的,以后要多重视中后期题,把细节理清楚。后期题可不是闹着玩的。

希望下场比赛能打出水平吧


K题已补,一遍BFS+一遍DFS,非常好写,为啥当时就没想到呢
代码如下

#include 
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
const int N = 55;
const int M = N * N;
const int inf = 1e9;
int n, m;
int w[M];
int hd[N];
class edge {
   public:
    int to, nxt;
    int c;

} e[M];
int ind = 1;
void add(int u, int v, int c, int i) {
    e[i].to = v;
    e[i].c = c;
    e[i].nxt = hd[u];
    hd[u] = i;
}
int dis[N];
void bfs() {
    rep(i, 1, n) dis[i] = inf;
    dis[1] = 0;
    queue q;
    q.push(1);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = hd[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (dis[v] > dis[u] + 1) {
                dis[v] = dis[u] + 1;
                q.push(v);
            }
        }
    }
}

int cnt[M];
int cost[N];
void dfs(int u, int cur_cost) {
    cost[u] = min(cost[u], cur_cost);
    for (int i = hd[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (dis[v] != dis[u] + 1) continue;
        ++cnt[e[i].c];
        dfs(v, cur_cost + cnt[e[i].c] * w[e[i].c]);
        --cnt[e[i].c];
    }
}

int main() {
    scanf("%d%d", &n, &m);
    rep(i, 1, m) scanf("%d", &w[i]);
    rep(i, 1, n) hd[i] = 0, cost[i] = inf;
    rep(i, 1, m) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        add(u, v, c, ++ind);
        add(v, u, c, ++ind);
    }
    bfs();
    rep(i, 1, m) cnt[i] = 0;
    dfs(1, 0);
    rep(i, 2, n) printf("%d\n", cost[i]);
    return 0;
}

你可能感兴趣的:(ACM,随笔,算法)