ICPC 2019 徐州

ICPC 2019 徐州

M Kill the tree

题意:求一棵有根树中,以每个节点为根的子树的所有重心

思路:

  • 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
  • 一棵树最多有两个重心,且相邻。
  • 重心一定在以重儿子为根的子树的重心到该点的路径上。

维护当前结点子节点个数与深度。

自底向上更新的时候,需要判断当前边的贡献如果 s z [ t ] < s z [ u ] − s z [ t ] sz[t] < sz[u] - sz[t] sz[t]<sz[u]sz[t]则继续往上走。

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

using namespace std;
const int MAXN = 2e5 + 50;
int id = 0;

struct Edge{
    int to, next;
}E[MAXN * 2];

int head[MAXN], f[MAXN], d[MAXN], sz[MAXN];
int son[MAXN], fath[MAXN];

vector<int>ans[MAXN];

void addedge(int u, int v)
{
    E[id].to = v;
    E[id].next = head[u];
    head[u] = id++;
}

void dfs1(int u, int fa)
{
    sz[u] = 1;
    for(int i = head[u]; i != -1; i = E[i].next)
    {
        int p = E[i].to;
        if(p == fa) continue;
        d[p] = d[u] + 1;
        fath[p] = u;
        dfs1(p, u);
        sz[u] += sz[p];
        if(sz[p] > sz[son[u]]) son[u] = p;
    }
}

void dfs2(int u, int fa)
{
    for(int i = head[u]; i != -1; i = E[i].next)
    {
        int p = E[i].to;
        if(p == fa) continue;
        dfs2(p, u);
    }
    f[u] = u;
    if(!son[u]) return;
    int t = f[son[u]];
    while(d[t] > d[u] && sz[t] < sz[u] - sz[t]) t = fath[t];
    f[u] = t;
}

int main()
{
    int n;
    scanf("%d", &n);
    memset(head, -1, sizeof(head));
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        addedge(u, v), addedge(v, u);
    }

    dfs1(1, -1);
    dfs2(1, -1);

    for(int i = 1; i <= n; i++)
    {
        ans[i].push_back(f[i]);
        if(fath[f[i]] && sz[f[i]] == sz[i] - sz[f[i]]) ans[i].push_back(fath[f[i]]);
        sort(ans[i].begin(), ans[i].end());
        if(ans[i].size() == 1) printf("%d\n", ans[i][0]);
        else printf("%d %d\n", ans[i][0], ans[i][1]);
    }

    return 0;
}

A Cat

思维题:可以发现从偶数开始连续四个数异或和为0

于是,分类讨论各种情况即可。

注:运算符优先级,len=4的情况单独分类。


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

using namespace std;
typedef long long ll;
int T;

int main()
{
    scanf("%d", &T);
    while(T--)
    {
        ll l, r, s;
        scanf("%lld%lld%lld", &l, &r, &s);
        ll len = r - l + 1;
        if(len == 1)
        {
            if(s >= l) printf("1\n");
            else printf("-1\n");
        }
        else if(len == 2)
        {
            int ans = -1;
            if(l <= s) ans = 1;
            if((l ^ r) <= s) ans = 2;
            printf("%d\n", ans);
        }
        else if(len == 3)
        {
            int ans = -1;
            if(l <= s) ans = 1;
            if((l ^ (l + 1)) <= s || ((l + 1) ^ r) <= s) ans = 2;
            if((l ^ (l + 1) ^ r) <= s) ans = 3;
            printf("%d\n", ans);
        }
        else if(len == 4)
        {
            int ans = -1;
            if(s >= 1) ans = 2;
            if((l ^ (l + 1) ^ (l + 2)) <= s || (r ^ (l + 1) ^ (l + 2)) <= s) ans = 3;
            if((l ^ (l + 1) ^ (l + 2) ^ (r)) <= s) ans = 4;
            printf("%d\n", ans);
        }
        else {
            ll ans = len / 4 * 4;
            if(len % 4 == 0)
            {
                if(l % 2 == 1)
                {
                    ans -= 4;
                    if((l ^ (l + 1) ^ (l + 2) ^ r) <= s) ans += 4;
                    else if((l ^ (l + 1) ^ (l + 2)) <= s || (r ^ (l + 1) ^ (l + 2)) <= s) ans += 3;
                    else if(s >= 1) ans += 2;
                }
            }
            else if(len % 4 == 1)
            {
                if(l % 2 == 1)
                {
                    if(l <= s) ans ++;
                }
                else {
                    if(r <= s) ans ++;
                }
            }
            else if(len % 4 == 2)
            {
                if(l % 2 == 0)
                {
                    if(s >= 1) ans += 2;
                }
                else {
                    if((l ^ r) <= s) ans += 2;
                    else if(l <= s) ans ++;
                }
            }
            else {
                if(l % 2 == 1)
                {
                    if((l ^ (r - 1) ^ r) <= s) ans += 3;
                    else if(s >= 1) ans += 2;
                }
                else {
                    if(((r - 2) ^ (r - 1) ^ r) <= s) ans += 3;
                    else if(s >= 1) ans += 2;
                }
            }
            printf("%lld\n", ans);
        }
    }

    return 0;
}

C. ❤️ numbers

给定一个区间,问是否区间长度与区间内质数之比>3

小区间特判,大区间直接Yes

注意:1在本题满足质数条件。

F. The Answer to the Ultimate Question of Life, The Universe, and Everything.

题意:问 a 3 + b 3 + c 3 = x a^3+b^3+c^3=x a3+b3+c3=x a , b , c a,b,c a,b,c

因为x的范围为 [ 0 , 200 ] [0,200] [0,200]

a,b,c范围 [ − 5000 , 5000 ] [-5000, 5000] [5000,5000]

所以直接打表枚举 a , b a,b a,b,二分 c c c,大概十分钟能出答案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值