Educational Codeforces Round 78 (Rated for Div. 2) 题解

  • Shuffle Hashing
  • A and B
  • Berry Jam
  • Segment Tree
  • Tests for problem D
  • Cards

Shuffle Hashing

\[
Time Limit: 2 s\quad Memory Limit: 256 MB
\]
处理出 \(s_1\) 中各个字符出现的次数,然后双指针维护 \(s_2\) 中每一段长度为 \(len(s_1)\) 的串中字符出现的次数,如果存在某一段和 \(s_1\) 的字符次数相同,则是答案。

view

#include <map>
#include <set>
#include <list>
#include <tuple>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e2 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m, k;
int cas, tol, T;

int cnt[26];
char s1[maxn], s2[maxn];

bool ok() {
    for(int i=0; i<26; i++) if(cnt[i])  return 0;
    return 1;
}

int main() {
    scanf("%d", &T);
    while(T--) {
        mes(cnt, 0);
        scanf("%s%s", s1+1, s2+1);
        n = strlen(s1+1), m = strlen(s2+1);
        if(n>m) {
            puts("NO");
            continue;
        }
        for(int i=1; i<=n; i++) cnt[s1[i]-'a']++;
        for(int i=1; i<=n; i++) cnt[s2[i]-'a']--;
        bool f = 0;
        for(int i=n; i<=m; i++) {
            if(ok())    f = 1;
            if(i==m)    break;
            cnt[s2[i+1]-'a']--;
            cnt[s2[i-n+1]-'a']++;
        }
        puts(f ? "YES" : "NO");
    }
    return 0;
}

A and B

\[
Time Limit: 1 s\quad Memory Limit: 256 MB
\]
说出来你可能不信,强行 \(oeis\) 过了。

view

#include <map>
#include <set>
#include <list>
#include <tuple>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

ll n, m;
int cas, tol, T;

int main() {
    scanf("%d", &T);
    while(T--) {
        ll a, b;
        scanf("%lld%lld", &a, &b);
        n = abs(a-b);
        ll k=0;
        for(; ; k++) {
            if(k*(k+1)/2 <= n && n<(k+1)*(k+2)/2)   break;
        }
        ll tk = k*(k+1)/2;
        ll ans;
        if(n == tk) ans = k;
        else {
            if(k%2 == 1) {
                if((n-tk)%2==1) ans = k+2;
                else    ans = k+1;
            } else {
                if((n-tk)%2==1) ans = k+1;
                else    ans = k+3;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

Berry Jam

\[
Time Limit: 2 s\quad Memory Limit: 256 MB
\]
预处理后半段中 \(1\) 比 \(2\) 多吃 \(x\) 瓶所需要的最少步数,然后枚举前半段中吃到第 \(i\) 瓶处,\(1\) 还需要比 \(2\) 多吃 \(y\) 瓶,然后在后半段预处理中找答案。

view

#include <map>
#include <set>
#include <list>
#include <tuple>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int a[maxn];
unordered_map<int, int> mp;

int main() {
    scanf("%d", &T);
    while(T--) {
        mp.clear();
        scanf("%d", &n);
        int y = 0;
        for(int i=1; i<=n+n; i++) {
            scanf("%d", &a[i]);
            y += a[i]==1 ? 1:-1;
        }
        if(y == 0) {
            printf("0\n");
            continue;
        }
        mp[0] = 0;
        for(int i=n+1, x=0; i<=n+n; i++) {
            x += a[i]==1 ? 1:-1;
            if(!mp.count(x))    mp[x] = i-n;
        }
//      for(auto t : mp)    printf("%d %d\n", t.fi, t.se);
        int ans = inf;
        for(int i=n; i>=0; i--) {
            if(mp.count(y))
                ans = min(ans, n-i+mp[y]);
            if(!i)  break;
            y -= a[i]==1 ? 1:-1;
        }
        printf("%d\n", ans);
    }
    return 0;
}

Segment Tree

\[
Time Limit: 2 s\quad Memory Limit: 256 MB
\]
把线段先按 \(l\) 在按 \(r\) 排序,然后枚举第 \(i\) 条线段,判断它可以和哪些线段连边。

可以发现,在枚举第 \(i\) 条线段时,前 \(i-1\) 条线段的 \(l\) 一定都是比我的 \(l\) 小的,所以我其实是需要找到前 \(i-1\) 条线段中,找到所有满足 \(p[i].l \leq p[j].r \leq p[i].r\) 的所有 \(j\)。

这一段区间是连续的,所以我们可以维护一个 \(set\) 的 \(pair\),用来存放前 \(i-1\) 条边的 \(r\) 位置和编号。然后用 \(set\) 的二分来快速找到所有的 \(j\)。

又因为想要形成一棵树,这也就意味着最多只会添加 \(n-1\) 条边,那么整体复杂度就不会太大。

view

#include <map>
#include <set>
#include <list>
#include <tuple>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  l          first
#define  r          second
#define  pb         push_back
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int fa[maxn];
pii p[maxn];
set<pii> st;

int find(int x) {
    return fa[x]==x ? x : fa[x]=find(fa[x]);
}

bool bind(int x, int y) {
    x = find(x), y = find(y);
    if(x == y)  return 0;
    fa[x] = y;
    return 1;
}

int main() {
    scanf("%d", &n);
    for(int i=1; i<=n; i++) {
        scanf("%d%d", &p[i].l, &p[i].r);
        fa[i] = i;
    }
    sort(p+1, p+1+n);
    st.clear();
    int sz = 0, f = 1;
    for(int i=1; i<=n; i++) {
        auto pos = st.lower_bound({p[i].l, -1});
        for(auto j = pos; j!=st.end(); j++) {
            if((*j).l > p[i].r) break;
            sz++;
            if(sz==n || !bind(i, (*j).r)) {
                f = 0;
                break;
            }
        }
        if(!f)  break;
        st.insert({p[i].r, i});
    }
    set<int> ans;
    for(int i=1; i<=n; i++) ans.insert(find(i));
    puts(ans.size()==1&&f ? "YES" : "NO");
    return 0;
}

Tests for problem D

\[
Time Limit: 2 s\quad Memory Limit: 256 MB
\]
考虑模拟一下第一个样例,它的放置规则是先把 \(1\) 看成整棵树的根,那么可以先确定 \(p[1].r = 2*n\),然后它有两个直接儿子,所以我需要在 \(r\) 前面留两个空给这两个儿子放 \(r\) 用,现在已经没有直接儿子了,为了防止新的交叉出现,接下来我就放上自己的 \(l\),对于下面的儿子也是同理,可以递归处理。

然后就是儿子的 \(l\) 问题了,由于 \(1\) 的各个儿子不能有交叉部分,也就意味着这些得是重合起来的,所以一开始放在最后的 \(r\),其对应的 \(l\) 就应该尽量小,所以我越早放在后面的儿子,应该越晚去 \(dfs\) 确定其 \(l\)。

为了防止数字重复被用到,可以用一个 \(set\) 来维护还可以用的数字。

view

#include <map>
#include <set>
#include <list>
#include <tuple>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  l          first
#define  r          second
#define  pb         push_back
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

set<int> st;
pii p[maxn];
vector<int> g[maxn];

void dfs(int u, int fa) {
    int len = g[u].size();
    for(int i=0; i<len; i++) if(g[u][i] != fa) {
        p[g[u][i]].r = *(--st.end());
        st.erase((--st.end()));
    }
    p[u].l = *(--st.end());
    st.erase((--st.end()));
//  printf("p%d .l = %d .r = %d\n", u, p[u].l, p[u].r);
    for(int i=len-1; ~i; i--) if(g[u][i] != fa) {
        dfs(g[u][i], u);
    }
}

int main() {
    scanf("%d", &n);
    for(int i=2, u, v; i<=n; i++) {
        scanf("%d%d", &u, &v);
        g[u].pb(v), g[v].pb(u);
    }
    p[1].r = 2*n;
    for(int i=1; i<2*n; i++)    st.insert(i);
    dfs(1, 1);
    for(int i=1; i<=n; i++) printf("%d %d\n", p[i].l, p[i].r);
    return 0;
}
/*
3
1 2
1 3
*/

Cards

\[
Time Limit: 4 s\quad Memory Limit: 256 MB
\]
留坑

原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/12075688.html

时间: 2024-09-30 11:45:17

Educational Codeforces Round 78 (Rated for Div. 2) 题解的相关文章

Educational Codeforces Round 36 (Rated for Div. 2) 题解

Educational Codeforces Round 36 (Rated for Div. 2) 题目的质量很不错(不看题解做不出来,笑 Codeforces 920C 题意 给定一个\(1\)到\(n\)组成的数组,只可以交换某些相邻的位置,问是否可以将数组调整为升序的 解题思路 首先如果每个数都能通过交换到它应该到的位置,那么就可以调整为升序的. 但实际上交换是对称的,如果应该在的位置在当前位置前方的数都交换完成,那么整体就是排好序的,因为不可能所有不在相应位置的数都在相应位置的后方.

Educational Codeforces Round 78 (Rated for Div. 2) D. Segment Tree

链接: https://codeforces.com/contest/1278/problem/D 题意: As the name of the task implies, you are asked to do some work with segments and trees. Recall that a tree is a connected undirected graph such that there is exactly one simple path between every

Educational Codeforces Round 78 (Rated for Div. 2) B. A and B

链接: https://codeforces.com/contest/1278/problem/B 题意: You are given two integers a and b. You can perform a sequence of operations: during the first operation you choose one of these numbers and increase it by 1; during the second operation you choos

Educational Codeforces Round 78 (Rated for Div. 2) A. Shuffle Hashing

链接: https://codeforces.com/contest/1278/problem/A 题意: Polycarp has built his own web service. Being a modern web service it includes login feature. And that always implies password security problems. Polycarp decided to store the hash of the password

【cf比赛记录】Educational Codeforces Round 78 (Rated for Div. 2)

比赛传送门 A. Shuffle Hashing 题意:加密字符串.可以把字符串的字母打乱后再从前面以及后面接上字符串.问加密后的字符串是否符合加密规则. 题解:字符串的长度很短,直接暴力搜索所有情况 // https://codeforces.com/contest/1278/problem/A #include<iostream> #include<cstdio> #include<cstring> using namespace std; int T; char

Educational Codeforces Round 78 (Rated for Div. 2) --补题

链接 直接用数组记录每个字母的个数即可 #include<bits/stdc++.h> using namespace std; int a[26] = {0}; int b[26] = {0}; int judge() { //cout<<"111"<<endl; for (int i = 0; i < 26; ++i) { if (a[i]!=b[i]) { return 0; } } return 1; } int main() { //

Educational Codeforces Round 78 (Rated for Div. 2)

C - Berry Jam 题意:给2n个罐子,分别是[1,2n],站在[n,n+1]的中间,吃掉包含这个点的左边连续一段和右边连续一段,使得剩下的罐子红色的和蓝色的数量相等.吃最少的罐子. 题解:把红色蓝色变成+1和-1,那么就把左边的前缀和插进map里面,然后右边的后缀和在map里面查询相反数,查到就更新.注意因为是吃得越少越好所以同一个值,map里存的应该是最靠右的前缀. 注意!要加上为0的前缀和和后缀和! 不过现场可以看出来并造样例验证,也是能力提高了一点. 4 1 1 1 1 1 2

Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam

Karlsson has recently discovered a huge stock of berry jam jars in the basement of the house. More specifically, there were 2n2n jars of strawberry and blueberry jam. All the 2n2n jars are arranged in a row. The stairs to the basement are exactly in

Educational Codeforces Round 58 (Rated for Div. 2) (题解)

C题卡了一个小时, 又被教育场教育了... A. Minimum Integer 大意:求不在$[l,r]$范围内的最小被$d$整除的数 模拟 #include <iostream> #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; int main() { int t; scanf("%d", &t); REP(i,1,t) { int l,r,d; scanf("%d%d%