Educational Codeforces Round 78

Posted lordxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 78相关的知识,希望对你有一定的参考价值。

A题:暴力然后排序用string比较就好。


B题:找规律?可能emm
首先第i次加i,记前缀和为sum,要两个数字相等,至少sum>=两个数字的差。
我们进一步思考,当sum!=差的时候,记sum-dis=x。
如果x是偶数,x/=2,然后该数字x一定是出现在sum里面的数字,我们将x分给大的数字,那么大数字增加x,小数字减小x,就可以相等了。
当x是奇数,我们没有办法相等,继续加上i+1,i+2..直到奇偶一样。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t;
const int N = 1e5+10;
int n = 1e5;
int a, b;
ll sum[N];
void init()
{
    upd(i, 1, 1e5)
    {
        sum[i] = sum[i - 1] + i*1ll;
    }
    sort(sum, sum + n);
}
int main()
{
    t = read();
    while (t--)
    {
        init();
        a = read(), b = read();
        int dis = abs(b - a);
        int temp = lower_bound(sum, sum + n, dis) - sum;
        while ((sum[temp] % 2) != (dis % 2))temp++;
        printf("%d
", temp);
    }
    return 0;
}

C题暴力模拟。
开一个map记录从n到1的后缀和的差,指的是,第i个位置,蓝莓和草莓的差值。
然后再从n+1的位置开始遍历。
差值的维护:
记n+1的位置蓝莓有x个,草莓y个。
一共有蓝莓n个,草莓m个。
记需要从n个里面删掉,o个蓝莓,p个草莓。
所以 n-o-x==m-y-p,移项得到,n-m=o-p+(x-y)
维护该差值即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t, n;
const int N = 2e5 + 10;
int a[N];
int sum1[N];
int sum2[N];
map<int, int>mp;
int main()
{
    t = read();
    while (t--) {
        n = read();
        upd(i, 0, 2 * n)sum1[i] = sum2[i] = 0;
        mp.clear();
        upd(i, 1, 2 * n)
        {
            a[i] = read();
            if (a[i] == 1)
            {
                sum1[i] = sum1[i - 1] + 1;
                sum2[i] = sum2[i-1];
            }
            else
            {
                sum2[i] = sum2[i - 1] + 1;
                sum1[i] = sum1[i-1];
            }
        }
        int dis = sum2[2 * n] - sum1[2 * n];
        if (dis == 0)
        {
            printf("%d
", 0); continue;
        }
        dwd(i, n, 1)
        {
            int temp = sum1[n] - sum1[i - 1];
            int temp2 = sum2[n] - sum2[i - 1];
            temp2 -= temp;
            //printf("%d ", temp2);
            if (!mp[temp2])
            {
                mp[temp2] = i;
            }
        }
        //cout << endl;
        mp[0] = n + 1;
        int ans = inf;
        if (mp.find(dis)!=mp.end())
        {
            ans = n-(*mp.find(dis)).second+1;
        }
        upd(i, n + 1, 2 * n)
        {
            int temp = sum1[i] - sum1[n];
            int temp2 = sum2[i] - sum2[n];
            temp2 -= temp;
            temp2 = dis - temp2;
            //printf("%d ", temp2);
            if (mp.find(temp2) != mp.end())
            {
                int k = (*mp.find(temp2)).second;
                ans = min(ans, i - k + 1);
            }
        }
        //cout << endl;
 
        printf("%d
", ans);
    }
    return 0;
}

D题
暴力and并查集
首先偏序问题,肯定排序解决一维,达到降维的目的。
我们按照线段的左端点排序。考虑右端点。
我们维护一个set,储存前i-1个的右端点。当前第i个,因为左端点已经被排序,只用考虑右端点,看是否大于set的里面的右端点,有的话加入并查集。
为了使得左端小于右端点,我们将所有右端点小于左端点的全部删掉,动态维护set。(感觉好套路。。cf出了多少道这样的题目了)
最后时间复杂度,虽然看似n^2,但其实我们因为是要建立一棵树,所以并查集不可能添加n-1次以上操作,所以复杂度就是on。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e5 + 10;
vector<pir>vec;
set<pir> s;
int n;
int pr[N];
int height[N];
void init()
{
    upd(i, 0, n)pr[i] = i, height[i] = 1;
}
int find_pr(int x)
{
    return pr[x] == x ?x: pr[x] = find_pr(pr[x]);
}
bool unit(int x,int y)
{
    x = find_pr(x);
    y = find_pr(y);
    if (x == y)return false;
    if (height[x] < height[y])swap(x, y);
    pr[y] = x;
    height[x] += height[y];
    return true;
}
int main()
{
    n = read();
    up(i, 0, n)
    {
        int x, y;
        x = read(), y = read();
        vec.push_back(make_pair(x, y));
    }
    init();
    sort(vec.begin(), vec.end());
    int cnt = 0;
    bool flag = 0;
    up(i, 0, n)
    {
        while (!s.empty() && s.begin()->first < vec[i].first)s.erase(s.begin());
        for (auto k : s)
        {
            if (k.first > vec[i].second)break;
            if(unit(k.second, i+1))
                cnt++;
            else flag = 1;
        }
        if (cnt > n - 1) {
            flag = 1;
        }
        if (flag == 1)break;
        s.insert(make_pair(vec[i].second,i + 1));
    }
    if (cnt != n - 1)flag = 1;
    int sum = 0;
    upd(i, 1, n)
    {
        if (pr[i] == i)sum++;
    }
    if (sum != 1)flag = 1;
    if (flag)printf("NO
");
    else printf("YES
");
    return 0;
}

E题:赛后补出,感觉这个构造很漂亮啊。
构造:
针对一个点u,令lf=tot,顺序遍历他的邻接子节点,邻接子节点lf=tot++,
在反向dfs他的邻接子节点即可。
这样就能保证,子节点全部和他相交,精髓在反向遍历,这样他的子节点,一定不相交,并且相容。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e5 + 10;
int n;
map<int, int>lf,rt;
vector<int>vec[N];
int tot = 1;
void dfs(int u, int fa)
{
    for (auto k : vec[u])
    {
        if (k == fa)continue;
        lf[k] = tot++;
    }
    rt[u] = tot++;
    vector<int>temp(vec[u]);
    reverse(temp.begin(), temp.end());
    for (auto k : temp)
    {
        if (k == fa)continue;
        dfs(k, u);
    }
}
int main()
{
    n = read();
    int u, v;
    up(i, 0, n - 1)
    {
        u = read(), v = read();
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    lf[1] = tot++;
    dfs(1, 0);
    upd(i, 1, n)
    {
        printf("%d %d
", lf[i], rt[i]);
    }
    return 0;
}

以上是关于Educational Codeforces Round 78的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27