CF Ozon Tech Challenge 2020 (Div.2)

掉了许多的 rating 终于涨了点。

A - Kuroni and the Gifts

此题做法显然,他告诉你不能有两个数之和是一样的,那么我们将两个序列从小至大排序,然后,输出即可

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef long long ll;

#define get() getchar()
#define problem AC
#define inf 1r7

using namespace std;

const int Maxn = 10000;

int a[Maxn], b[Maxn], t, n;

int main() {
    t = read();
    while(t--) {
        n = read();
        for(int i = 1; i <= n; ++i) a[i] = read();
        for(int i = 1; i <= n; ++i) b[i] = read();
        sort(a + 1,a + 1 + n);
        sort(b + 1,b + 1 + n);
        for(int i = 1; i <= n; ++i) printf("%d ",a[i]);
        printf("\n");
        for(int i = 1; i <= n; ++i) printf("%d ",b[i]);
        printf("\n");
    }
    
    return 0;
}

改了码风后,确实可读多了

B - Kuroni and Simple Strings

我们贪心的想,就从左到右扫,每一次去掉一个 simple 序列,想一想为什么

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef long long ll;

#define get() getchar()
#define problem AC
#define inf 1r7

using namespace std;

const int Maxn = 1003;

int k, len, now,ans[Maxn][Maxn];

char c[Maxn];

bool flag[Maxn];

bool check(int k) {
    int nowk =k + 1, sum = 0;
    for(int l = 1, r = len; l <= len && l < r; ++l) {
        if(flag[l]) continue;
        if(c[l] == '('){
            bool flag1 = 1;
            for(; r>l; r--){
                if(!flag[r] && c[r] == ')'){
                    flag1 = 0;
                    ans[nowk][++sum] = l;
                    ans[nowk][++sum] = r;
                    flag[l] = flag[r] =1;
                    break;
                } 
            }
            if(flag1) break;
        }
    }
    ans[nowk][0] = sum;
    sort(ans[nowk] + 1, ans[nowk] + 1 + sum);
    return sum != 0;
}

int main() {
    scanf("%s", c + 1);
    len = strlen(c + 1);
    for(int i = 1; i <= k; ++i) id[i] = i;
    while(check(k)) k++;
    printf("%d\n", k);
    for(int i = 1; i <= k; ++i) {
        printf("%d\n",ans[i][0]);
        for(int j = 1;j <= ans[i][0]; ++j) {
            printf("%d ", ans[i][j]);
        }
        printf("\n");
    }
    return 0;
}

更好的想,我们不妨记下每次的右指针。。。你懂的。

C - Kuroni and Impossible Calculation

此题真是大坑,注意观察数据范围。。
\[ 2 \le n \le 2\times 10^5, 2\le m \le 1000 \]
所以,他的答案是要求对于 m 取模,所以 若有一对 \(a_i,a_j\) 满足 \(|a_i-a_j|=km\) 于是答案就是零。。惊喜吗

若没有这样的。。就爆算吧。反正 \(n \le m \le 1000\)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef long long ll;

#define get() getchar()
#define problem AC
#define inf 1r7

using namespace std;

const int Maxn = 2e5 + 11;

ll n, m, a[Maxn], b[Maxn], ans;

bool cmp(ll a, ll b) {
    return a > b;
}

int main() {
    n = read(); m = read();
    for(int i = 1; i <= n; ++i) {
        a[i] = read();
        b[a[i]%m]++;
        if(b[a[i]%m] > 1) {
            printf("0");
            return 0;
        }
    }
    sort(a+1,a+1+n,cmp);
    ans =1;
    for(int i = 1;i<=n;i++){
        for(int j= i+1;j<=n;j++){
            ans =(ans *(a[i]-a[j]))%m;
        }
    }
    printf("%lld", ans);
    return 0;
}

事实上,没有比 \(O(n^2)\) 再优的了

D - Kuroni and the Celebration

此题要求我们求根,事实上,我们每次可以选择树的直径,询问直径的端点的最近公共祖先,就行了。

然后删去直径上,与 LCA 不一样的点,最后当只剩一个点时,就是我们的答案

#include <cstdio>
#include <cstring>

const int Maxn = 2009;

int n, h[Maxn], cnt, rt, jb, fa[Maxn], dep[Maxn];

bool vis[Maxn];

struct Edge {
    int to, lac;
    void insert(int x, int y) {to = y; lac = h[x]; h[x] = cnt++;}
}edge[Maxn];

void add_edge(int y, int x) {edge[cnt].insert(x, y); edge[cnt].insert(y, x);}

void dfs(int u) {
    dep[u] = dep[fa[u]] + 1;
    if(dep[u] > dep[jb]) jb = u;
    for(int i = h[u]; i != -1; i = edge[i].lac) {
        int to = edge[i].to;
        if(vis[to] || to == fa[u]) continue;
        fa[to] = u; dfs(to);
    }
}

int main() {
    n = read(); memset(h, -1, sizeof h);
    for(int i = 1; i < n; ++i) add_edge(read(), read());
    rt = 1;
    while(1) {
        jb = fa[rt] = 0; dfs(rt);
        int t = jb; fa[t] = jb = 0; dfs(t);
        if(t == rt && rt == jb) {
            printf("! %d\n", rt); 
            fflush(stdout);
            return 0;
        }
        printf("? %d %d\n", t, jb);
        fflush(stdout);
        rt = read();
        for(int i = fa[jb]; i; i = fa[i]) vis[i] = 1;
        vis[rt] = 0;
    }
    return 0;
}

庆祝人生第一道交互题

猜你喜欢

转载自www.cnblogs.com/zhltao/p/12407818.html