ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Educational Codeforces Round 104 (Rated for Div. 2)

2021-02-16 12:01:37  阅读:193  来源: 互联网

标签:rt Educational Rated int Codeforces long Mid 平局 define


A - Arena

题意

有一堆人打架,两个人打架战斗力强的赢,相等就谁也不赢。
问每次随机挑一对人打架,有多少人可能一直赢。

题解

随机就是说每个人只会跟最弱的打,如果当前人比最弱的强ans就+1。

#include <bits/stdc++.h>
#define int long long
#define Mid ((l + r) >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read(){
    char c; int num, f = 1;
    while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    return f * num;
}
int n, a[100009], cnt;
void work() {
    n = read(); cnt = 0;
    for(int i = 1; i <= n; i++) a[i] = read();
    sort(a + 1, a + 1 + n);
    for(int i = 1; i <= n; i++) {
        cnt += a[i] != a[1];
    }
    printf("%lld\n", cnt);
}
signed main()
{
    int Case = read();
    while(Case--) work();
    return 0;
}
View Code

 

B - Cat Cycle

题意

有两只猫要睡觉,A猫第一天睡\(n\)号点,第二天睡\(n-1\)号点,第\(n+1\)天回到\(n\)号点睡觉,以此类推。
B猫从\(1\)号点开始往后睡,但是B猫干不过A猫,如果B猫和A猫下一天会到同一个地方睡觉,则B猫会跳过那个位置,到下一天的位置睡。
现在问第\(k\)天B猫睡在哪里。

题解

首先如果\(n\)是偶数,他们就不会睡在同一个地方,直接\(k\)对\(n\)取模即可。
如果是奇数,说明有冲突,观察冲突是如何发生的。
AB猫一开始面对面,然后走\(\lfloor\frac{n}{2}\rfloor\)格之后就会撞到,然后B猫多走一步。
然后AB猫变成背对背相邻了,把\(n\)格铺开,其实问题又跟之前一样了,所以一共撞到\(\frac{k}{\frac{n}{2}}\)次,就是多走这么多步,加上之后还是取模即可。

#include <bits/stdc++.h>
#define int long long
#define Mid ((l + r) >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read(){
    char c; int num, f = 1;
    while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    return f * num;
}
int n, k;
void work() {
    n = read(); k = read();
    if(n& 1) {
        k -= 1;
        k += k / (n / 2);
        k = k % n + 1;
        printf("%lld\n", k);
    } else {
        printf("%lld\n", (k - 1) % n + 1);
    }
}
signed main()
{
    int Case = read();
    while(Case--) work();
    return 0;
}
View Code

 

C - Minimum Ties

题意

一堆人打架,打赢了加3分,输了不加分,平局各加一分。
构造一种比赛状况使得最后总分一样的前提下平局最少。

题解

可以列一张表格\(g[i][j] = -g[i][j]\), 平局为0。

首先如果是奇数个队伍的话就直接没有平局就行了,每个人赢\(\frac{n - 1}{2}\)场。
第一个人是\(x,1,1,1,-1,-1,-1\)的,第二个人是\(-1,x,1,1,1,-1,-1\),\(x\)表示没有这场比赛。
发现这东西是循环的。

然后考虑偶数,偶数的话不可能没有平局,就加入一场平局。
发现由于平局加的不是完整的3分,所以一旦一个人有了平局,就所有人都得有平局。
把第一个人改成\(1,1,0,-1,-1\)就行了。
(考场上降智,脑筋急转弯题杀我。)

#include <bits/stdc++.h>
#define Mid ((l + r) >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read(){
    char c; int num, f = 1;
    while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    return f * num;
}
void work() {
    int n = read();
    if(n & 1) {
        for(int i = 1; i <= n; i++)
            for(int j = i + 1, cnt = 1; j <= n; j++, cnt++)
                printf("%d ", (cnt & 1) ? 1 : -1);
    } else {
        for(int i = 1; i <= n; i++) {
            for(int j = i + 1; j <= n; j++) {
                if(j - i ==  (n - 2) / 2 + 1) printf("0 ");
                else if(j - i <= (n - 2) / 2) printf("1 ");
                else printf("-1 ");
            }
        }
    }
    printf("\n");
}
signed main()
{
    int Case = read();
    while(Case--) work();
    return 0;
}
View Code

 

D - Pythagorean Triples

题意

找到\(1\le a\le b \le c \le n\),使得\(a^2 = b + c\),并且有\(c^2 = a^2 + b^2\)的对数。

题解

还是考场降智我把直角三角形的条件看成是能组成三角形==。

看对题目这就是道傻逼题。

化简公式去掉\(a^2\),解出\(c = b + 1\), \(a^2 = 2b + 1\)。
显然a必须是奇数。

据说有\(O(1)\)写法,但我写法是二分。
因为一旦一个\(a\)可行,那么从\(3\)到这个\(a\)的所有奇数都可行,暴力二分就行了。

#include <bits/stdc++.h>
#define int long long
#define Mid ((l + r) >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read(){
    char c; int num, f = 1;
    while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    return f * num;
}
int n;
void work() {
    n = read();
    int l = 1, r = 1e5;
    while(l <= r) {
        int x = Mid * 2 + 1;
        if((x * x + 1) / 2 > n || x > n) r = Mid - 1;
        else l = Mid + 1;
    }
    printf("%lld\n", r);
}
signed main()
{
    int Case = read();
    while(Case--) work();
    return 0;
}
View Code

 

E - Cheap Dinner

题意

给定一张四层的分层图,每一层只会跟上一层有连边。
要求在每一层里面找出一个点,使得点是独立的并且点权和最小。
(独立指两两之间不能有连边)

题解

(最小点权独立集难道不是费用流吗)
由于只取一对,没必要用费用流。
考虑暴力dp。
每一个点的能不能取只跟上一层取了哪个点有关。
\(f[i][j]\)表示前i层,第i层的j点必须要取的最小代价。

\(f[i][j]\)从\(f[i - 1][k](k!=fa[j])\)转移而来。
但是对于一个点又很多个k,但是由于注意到边在均摊给每个点之后,每个点均摊到的边其实很少,所以对于每个点的转移,一整段的东西是很多的,可以考虑数据结构维护。
用线段树或者ST表都可,只要维护区间最小值就行了。

#include <bits/stdc++.h>
#define int long long
#define Mid ((l + r) >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read(){
    char c; int num, f = 1;
    while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    return f * num;
}
int n[5], a[5][150009], f[5][150009], tree[150009 * 4];
vector<int> fa[5][150009];
void update(int rt) {tree[rt] = min(tree[lson], tree[rson]);}
void build(int l, int r, int rt, int t) {
    if(l == r) {tree[rt] = f[t][l]; return ;}
    build(l, Mid, lson, t); build(Mid + 1, r, rson, t);
    update(rt);
}
int query(int l, int r, int L, int R, int rt) {
    if(L <= l && r <= R) return tree[rt];
    int ans = 0x3f3f3f3f3f3f3f3f;
    if(L <= Mid) ans = min(ans, query(l, Mid, L, R, lson));
    if(Mid <  R) ans = min(ans, query(Mid + 1, r, L, R, rson));
    return ans;
}
signed main()
{
    memset(f, 0x3f, sizeof(f));
    for(int i = 1; i <= 4; i++) 
        n[i] = read();
    for(int i = 1; i <= 4; i++)
        for(int j = 1; j <= n[i]; j++) a[i][j] = read();
    for(int i = 2; i <= 4; i++) {
        int m = read();
        for(int j = 1; j <= m; j++) {
            int x = read(), y = read();
            fa[i][y].push_back(x);
        }
    }
    for(int i = 2; i <= 4; i++) {
        for(int j = 1; j <= n[i]; j++) {
            fa[i][j].push_back(n[i - 1] + 1);
            sort(fa[i][j].begin(), fa[i][j].end());
        }
    }
    for(int i = 1; i <= n[1]; i++)
        f[1][i] = a[1][i];
    build(1, n[1], 1, 1);
    for(int i = 2; i <= 4; i++) {
        for(int j = 1; j <= n[i]; j++) {
            int now = 0, minn = 0x3f3f3f3f3f3f3f3f;
            for(auto nxt : fa[i][j]) {
                if(nxt - 1 >= now + 1) minn = min(minn, query(1, n[i - 1], now + 1, nxt - 1, 1));
                now = nxt;
            }
            f[i][j] = min(f[i][j], minn + a[i][j]);
        }
        build(1, n[i], 1, i);
    }
    int ans = 0x3f3f3f3f3f3f3f3f;
    for(int j = 1; j <= n[4]; j++)
        ans = min(ans, f[4][j]);
    printf("%lld\n", ans == 0x3f3f3f3f3f3f3f3f ? -1 : ans);
    return 0;
}
View Code

 

标签:rt,Educational,Rated,int,Codeforces,long,Mid,平局,define
来源: https://www.cnblogs.com/onglublog/p/14406372.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有