Codeforces Round #286 (Div. 1) 解题报告

A.Mr. Kitayuta, the Treasure Hunter

很显然的一个DP,30000的数据导致使用map+set会超时。题解给了一个非常实用的做法,由于每个点有不超过250种状态,并且这些状态都是以包含d连续的一段数字,那么可以以对d的偏移量作为状态。这算是很常见的一个优化了。

#include<bits/stdc++.h>
using namespace std;
const int INF = 30009;
int f[INF][500],a[INF];
int n, d, ans = 1, x;
int main() {
    scanf ("%d %d", &n, &d);
    for (int i = 1; i <= n; i++) {
        scanf ("%d", &x);
        a[x]++;
    }
    f[d][250] = a[d] + 1;
    for (int i = d; i <= x; i++)
        for (int j = 0; j < 500; j++) {
            if (f[i][j] == 0) continue;
            int k = j - 250 + d, val = f[i][j];
            ans = max (ans, val);
            for (int t = max (1, k - 1); t <= k + 1; t++)
                if (i + t <= x)
                    f[i + t][t - d + 250] = max (f[i + t][t - d + 250], val + a[i + t]);
        }
    printf ("%d\n", ans - 1);
}

B.Mr. Kitayuta‘s Technology

[Problem] Given an integer n and m pairs of integers (ai, bi) (1 ≤ ai, bi ≤ n), find the minimum number of edges in a directed graph that satisfies the following condition:

  • For each i, there exists a path from vertex ai to vertex bi.

对于一个n个点的强连通图最少需要n条边,而非强连通的n个有边连接的点最少需要n-1条边。那么只要判断连通起来的k个点组成的块是不是有环,如果有环需要k条边,无环需要k-1条边。在连完一个连通的块后将其合并看成一个点。直到所有点都遍历过。

#include<bits/stdc++.h>
using namespace std;
const int INF = 120009;
struct Edge {
    int v, next;
} edge[INF];
int head[INF], ncnt ;
int f[INF], vis[INF], cycle[INF], siz[INF];
int n, m, ans;
inline void adde (int u, int v) {
    edge[++ncnt].v = v, edge[ncnt].next = head[u];
    head[u] = ncnt;
}
inline int find (int x) {
    if (f[x] == x) return x;
    return f[x] = find (f[x]);
}
inline void uin (int x, int y)
{
    siz[find (x)] += siz[find (y)];
    f[find (y)] = find (x);
}
inline bool dfs (int u) {
    vis[u] = 1;
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (!vis[v])     dfs (v);
        if (vis[v] == 1) cycle[find (u)] = 1;
    }
    vis[u] = 2;
}
int main() {
    scanf ("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) f[i] = i, siz[i] = 1;
    for (int i = 1, x, y; i <= m; i++) {
        scanf ("%d %d", &x, &y);
        adde (x, y);
        if (find (x) != find (y) ) uin (x, y);
    }
    for (int i = 1; i <= n; i++)
        if (!vis[i]) dfs (i);
    for (int i = 1; i <= n; i++) {
        if (find (i) == i)
            ans += siz[i] - 1;
        ans += cycle[i];
    }
    printf ("%d\n", ans);
}

D.Mr. Kitayuta‘s Colorful Graph

题意:一个n个点m条边的无向图中所有的边都有一个颜色,有q个询问,对每个询问(u,v)输出从u到v的纯色路径条数。(n,m,q<1e5)

首先应该先把所有相同颜色边连接的块做一次并查集,然后对所有询问(a,b)对a,b中有着较少的度的点的颜色查找b是否与a在一个集合。

unordered_map能够在让查找b的时间降到O(1)

#include<bits/stdc++.h>
using namespace std;
const int INF = 100009;

unordered_map<int, int> f[INF], old[INF];

int n, m, q;
inline int find (int x, int c) {
    if (f[x][c] < 0) return x;
    return f[x][c] = find (f[x][c], c);
}
inline void merge (int x, int y, int c) {
    if (f[x].find (c) == f[x].end() ) f[x][c] = -1;
    if (f[y].find (c) == f[y].end() ) f[y][c] = -1;
    x = find (x, c), y = find (y, c);
    if (x == y) return;
    f[y][c] += f[x][c];
    f[x][c] = y;
}
int main() {
    scanf ("%d %d", &n, &m);
    for (int i = 1, x, y, c; i <= m; i++) {
        scanf ("%d %d %d", &x, &y, &c);
        merge (x, y, c);
    }
    scanf ("%d", &q);
    int a, b;
    while (q--) {
        scanf ("%d %d", &a, &b);
        if (f[a].size() > f[b].size() ) swap (a, b);
        if (old[a].find (b) == old[a].end() ) {
            int ans = 0;
            for (auto &c : f[a])
                if (f[b].find (c.first) != f[b].end() && find (a, c.first) == find (b, c.first) )
                    ans++;
            old[a][b] = ans;
        }
        printf ("%d\n", old[a][b]);
    }
}

时间: 2024-11-05 18:40:50

Codeforces Round #286 (Div. 1) 解题报告的相关文章

Codeforces Round #259 (Div. 2) 解题报告

终于重上DIV1了.... A:在正方形中输出一个菱形 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月01日 星期五 23时27分55秒 4 5 #include<vector> 6 #include<set> 7 #include<deque> 8 #include<stack> 9 #include<bitset> 10 #inclu

Codeforces Round #262 (Div. 2)解题报告

详见:http://robotcator.logdown.com/posts/221514-codeforces-round-262-div-2 1:A. Vasya and Socks   http://codeforces.com/contest/460/problem/A 有n双袜子,每天穿一双然后扔掉,每隔m天买一双新袜子,问最多少天后没有袜子穿.. 简单思维题:以前不注重这方面的训练,结果做了比较久,这种题自己边模拟边想.不过要多考虑trick ```c++ int main(){ i

Codeforces Round #616 (Div. 2)解题报告

Codeforces Round #616 (Div. 2)解题报告 A. Even But Not Even 找两个奇数就行了. #include<bits/stdc++.h> using namespace std; void solve() { int n; string s; cin >> n >> s; string ans = ""; for(int i = 0; i < n; i++) { if(int(s[i] - '0')%2

Codeforces Round #479 (Div. 3)解题报告

题目链接: http://codeforces.com/contest/977 A. Wrong Subtraction 题意 给定一个数x,求n次操作输出.操作规则:10的倍数则除10,否则减1 直接写,手速题,没啥好说的 B. Two-gram 题意 求出现次数最多的连续两个字符 还是签到题,我居然很麻烦地用了map,= =算了,思路畅通都无所谓了 #include <iostream> #include<stdio.h> #include<algorithm> #

Codeforces Round #515 (Div. 3) 解题报告(A~E)

题目链接:http://codeforces.com/contest/1066 A题: 题意:Vova想坐火车从1点到L点,在路上v的整数倍的点上分布着灯笼,而在路上从l到r处停着别的火车,它挡着Vova的视线使他看不到灯笼.给定L,v,l,r求Vova能看到的灯笼数. 分析:从1到x上所有的灯笼数量为x/v个.则路上所有的灯笼数为L/v个,被挡住的则为 r/v - (l-1)/v 个,相减即为答案. #include<iostream> #include<cstdio> #inc

Codeforces Round #401 (Div. 2)解题报告

A - Shell Game 1 #include <iostream> 2 #include<bits/stdc++.h> 3 #include <stack> 4 #include <queue> 5 #include <map> 6 #include <set> 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10

Codeforces Round #390 (Div. 2) 解题报告

时隔一个月重返coding…… 期末复习了一个月也不亏 倒是都过了…… 就是计组61有点亏 复变68也太低了 其他都还好…… 假期做的第一场cf 三道题 还可以…… 最后room第三 standing383简直人生巅峰…… 看楼上楼下都是两道题的 如果A题不错那么多估计能进前300了吧…… 这场倒是把之前两场的分加回来了 开头不错 这个假期争取紫名~ A.Lesha and array splitting 把给定的数组分割成几个区间 要求各个区间和不能为0 一开始没注意到分割之后的区间重新合成之

Codeforces Round #394 (Div. 2) 解题报告

开始补题,今天下午virtual参赛,过了ABC,D题因为一点小错误而没能在比赛时间中AC,时间到了之后几分钟就发现了问题所在,略有遗憾.之后一直冥思苦想E题,在提示下终于明白,真的是给这样组合题画风的题目跪了,只能说继续加油,扩展思路吧. A题 题目地址 只有奇偶数个数相差小于等于1时可以,需要特判不能使二者均为0的情况. 参考代码 1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream>

Codeforces Round #279 (Div. 2) 解题报告

A - Team Olympiad 贪心水题..都从第一个开始取即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map