Codeforces Round #623 (Div. 2, based on VK Cup 2019-2020 - Elimination Round, Engine)

题目链接:https://codeforces.com/contest/1315

A - Dead Pixel

诚心诚意的送分题。

题意:给一个n*m的格子矩阵,和一个坏掉的格子,找一个最大的不包含坏掉的格子的矩阵。

void test_case() {
    int n, m, x, y;
    scanf("%d%d%d%d", &n, &m, &x, &y);
    int ans = max(x * m, (n - (x + 1)) * m);
    ans = max(ans, max(y * n, (m - (y + 1)) * n));
    printf("%d\n", ans);
}

B - Homecoming

比A题还没意思。

C - Restoring Permutation

题意:构造一个字典序最小的2n个元素的排列,使得题目给出的数组b,满足 \(b_i=min(a_{2i-1},a_{2i})\) 。

题解:首先既然是排列,就要检查数组b的元素本身就不重复。而且数组b中不会出现2n。既然数组b是按最小值构造的,那么肯定把这个元素放在左边,也就是 \(a_{2i-1}=b_i\) 。然后右边那个数就贪心取第一个大于他的数,这样字典序最小,同时也节约了最小值意义下的资源。所以从左到右扫描,每个数选大于他的最小的还没被选的数搭档。好像也很没有意思,假如是要带log的做法,可以二分。假如是要接近常数的做法,可以用并查集实现的可删除链表,每个数存下一个可能没有被删除的数的位置。

D - Recommendations

题意:给n个数的数组x,以及n个数的数组t,把xi变为xi+1的消耗为ti,求最小的总消耗使得数组x中的元素各不相同。

题解:考虑一个暴力算法:首先,每次选择最小的xi,若xi无重复,则continue,否则,一直选择消耗ti最小的xi,把他变成xi+1,直到xi无重复。发现这个算法可以优化,就是每次依然是变成xi+1,但是只需要直接保留消耗ti最大的xi即可。

pii p[200005];
map<int, int> M;

void test_case() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &p[i].first);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &p[i].second);
    sort(p + 1, p + 1 + n);
    int curx = -1;
    ll sum = 0, ans = 0;
    for(int l = 1, r; l <= n; l = r + 1) {
        while(curx != -1 && curx != p[l].first) {
            auto it = M.rbegin();
            sum -= it->first;
            if(it->second == 1)
                M.erase(it->first);
            else
                it->second -= 1;
            ans += sum;
            curx += 1;
            if(M.empty())
                curx = -1;
        }
        curx = p[l].first;
        for(r = l; r + 1 <= n && p[r + 1].first == p[l].first; ++r);
        for(int i = l; i <= r; ++i) {
            M[p[i].second] += 1;
            sum += p[i].second;
        }
        auto it = M.rbegin();
        sum -= it->first;
        if(it->second == 1)
            M.erase(it->first);
        else
            it->second -= 1;
        ans += sum;
        curx += 1;
        if(M.empty())
            curx = -1;
    }
    while(curx != -1) {
        auto it = M.rbegin();
        sum -= it->first;
        if(it->second == 1)
            M.erase(it->first);
        else
            it->second -= 1;
        ans += sum;
        curx += 1;
        if(M.empty())
            curx = -1;
    }
    printf("%lld\n", ans);
}

但是其实ti的范围很小,不需要用map这么复杂也可以,用权值线段树就行。

1D - Tourism

题意:给n(<=80)个点的边带权有向完全图,边权由邻接矩阵给出,选出一个从1开始的边权最小的k(<=10)条边的回路(不一定是简单路径,也就是可以重复经过同一个点,也可以重复经过同一条边),要求这个回路中,不存在奇数条边的环。保证k是偶数。

假做法:假如没有“不存在奇数条边的环”这个限制,整一个分层图就可以,复杂度也对(相邻两层之间有n^2条边,一共800个点6400条边)。加上这个限制的话,只需要一开始预处理出一次经过两条边的路径,然后把路径抽象成新的边,再建一次分层图即可。这个算法是错的,样例都可以检查出来1->5->2->1->5,存在了一个奇数环。仔细研究发现分层图的想法没有保留到达这个点的时候经过了哪些点,所以也不能从中限制下一条边的取值,这个算法是不可行的。

题解1:枚举这条长度为k的路径中,出现在偶数位置的点,这些点至多有k/2个,其中这些点除了最后一个一定是1以外,其他的点都不能是1。共有n^{k/2-1}种路径,然后要在这些点之间连接边数为2的路径。因为不能出现奇数条边的环,所以不能通过已经被枚举的点来松弛,所以保留k/2+1条最短的边数为2的路径,把通过被枚举的点松弛的路径跳过,就得到了正确的路径。最后记得补上1到枚举的第一个点的边的长度。

题解2:随机算法:给所有点随机黑白染色,变成一个二分图,规定和1同色的称为黑色,那么需要找一条“黑(1)-白-黑-...-黑(1)”的路径,因为同一个点必是同色,所以这样的路径不存在奇数条边的环,然后用分层图O(k*E)跑出最短路(同一层之间没有边的分层图,是不需要dijkstra的,因为同一层之间先更新哪个是不影响的,本质上是个简单的DAG上动态规划,dijkstra因为可以解决无负权边的带环图的情况,导致复杂度变高)。

最坏情况下,k=10,除了1以外最短路最多有9个点,只有这条路上的点被唯一正确染色时,才会把这条最短路统计进去,单次染色就成功的概率为1/512。由于n和k很小,可以进行10000次随机染色,10000次都失败的概率是(511/512)^10000=3e-9。

收获:

1、最短路算法的特点:
floyd:复杂度高,多源最短路,可以处理负权边的情况,可以发现图中是否有负环。
SPFA:复杂度一般比floyd稍低,单源最短路,可以处理负权边的情况,可以发现图中包含源点的负环。
dijkstra:复杂度低,单源最短路,不能处理负权边的情况。
DAG上DP:复杂度比dijkstra还低,但只能处理DAG。

2、和奇数偶数相关的图,有可能变成二分图来思考。

3、数据量小但是又很少人过的题目,一般都是比较巧妙的枚举或者状压。也有可能因为数据量小可以使用多次随机的算法蒙混过关。

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12432306.html

时间: 2024-08-28 07:11:49

Codeforces Round #623 (Div. 2, based on VK Cup 2019-2020 - Elimination Round, Engine)的相关文章

Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Pattern Matching B. Pair of Toys C. Bracket Subsequence D. Array Restoration-区间查询最值(RMQ(ST))

Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Pattern Matching 题意就是匹配字符的题目,打比赛的时候没有看到只有一个" * ",然后就写挫了,被hack了,被hack的点就是判一下只有一个" * ". 1 //A 2 #include<iostream> 3 #include<cstdio&g

【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps

我们要统计的答案是sigma([L/K]),L为路径的长度,中括号表示上取整. [L/K]化简一下就是(L+f(L,K))/K,f(L,K)表示长度为L的路径要想达到K的整数倍,还要加上多少. 于是,我们现在只需要统计sigma((L+f(L,K))),最后除以K即可. 统计sigma(L)时,我们考虑计算每条边出现在了几条路径中,设u为edgei的子节点,那么这条边对答案的贡献就是siz(u)*(n-siz(u)),siz(u)为u的子树大小. 统计sigma(f(L,K))时,我们需要dp出

Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) -B C(GCD,最长连续交替序列)

B. Weakened Common Divisor time limit per test 1.5 seconds memory limit per test 256 megabytes input standard input output standard output During the research on properties of the greatest common divisor (GCD) of a set of numbers, Ildar, a famous mat

Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) B

Description Bear Limak examines a social network. Its main functionality is that two members can become friends (then they can talk with each other and share funny pictures). There are n members, numbered 1 through n. m pairs of members are friends.

Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) C

Description In the army, it isn't easy to form a group of soldiers that will be effective on the battlefield. The communication is crucial and thus no two soldiers should share a name (what would happen if they got an order that Bob is a scouter, if

Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) A

Description Bear Limak wants to become the largest of bears, or at least to become larger than his brother Bob. Right now, Limak and Bob weigh a and b respectively. It's guaranteed that Limak's weight is smaller than or equal to his brother's weight.

Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)C. Producing Snow+差分标记

题目链接:C. Producing Snow 题意:给两个数组v[N],T[N],v[i]表示第i天造的雪,T[i],表示第i天的温度,一堆雪如果<=T[i],当天就会融完,否则融化T[i],要求输出每天的融雪总量. 题解:我对T数组求个前缀和,就可以二分找到每堆雪在那一天(pos)融化,余下的要加进答案中ans[i],然后用一个an数组在a[i]+1,a[pos]-1,最后求再求一次前缀和. ans[i]再加上an[i]*t[i].每次操作二分logn,N次操作.复杂度O(nlogn) #in

Codeforces Round #472 (rated, Div. 2, based on VK Cup 2018 Round 2)

A. Tritonic Iridescence 题解:分类讨论.注意题目要求,至少有两种方案. 1 #pragma warning(disable:4996) 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 9 int n, m; 10 stri

Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) C. Stairs and Elevators【二分查找】

In the year of 30XX30XX participants of some world programming championship live in a single large hotel. The hotel has nn floors. Each floor has mm sections with a single corridor connecting all of them. The sections are enumerated from 11 to mm alo