首页 > 其他分享 >The 3rd Universal Cup. Stage 8: Cangqian

The 3rd Universal Cup. Stage 8: Cangqian

时间:2024-09-11 18:36:08浏览次数:13  
标签:return int res Universal Cangqian fa vector using Stage

C. Challenge NPC

考虑构造一个二分图,左边是\(1,3,5,7\)右侧是\(2,4,6,8\)。最优解肯定是一边全 1,一边全 2。

如果\(1,2\)之间不连边,这\(2\)就会被染色为 1,因此只要让\(2,3\)连边,\(3\)会被染色为\(2\),然后\(1,4\)连边,\(4\)也会被染色为\(5\),这时只要让\(2,5\)和\(4,5\)连边,\(5\)就会被染色为\(3\)。可以以此类推下去,这样左右的颜色都会依次是\(1,2,3,4,\dots\),因此只要让左右两侧都有\(k+2\)个点就好了

#include<bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int k;
    cin >> k;
    int n = (k + 2) * 2, m = n * (n - 2) / 4, c = 2;
    cout << n << " " << m << " " << c << "\n";
    for (int i = 1; i <= n; i++)
        cout << i % 2 + 1 << " ";
    cout << "\n";
    for (int i = 1, t; i <= n; i++) {
        t = i + 2;
        if (i & 1) t++;
        else t--;
        for (; t <= n; t += 2)
            cout << i << " " << t << "\n";
    }
    return 0;
}

E. Team Arrangement

假设我们知道分组的方案后,我们把组按照大小排序,然后贪心的选择\(r\)较小的即可。

然后考虑如果得到分组方案,因为\(n\)最大只有\(60\),所以直接暴搜枚举出来就好了。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;
using pii = pair<int, int>;

const int inf = LLONG_MAX / 2;


i32 main() {
    int n;
    cin >> n;
    vector<pii> a(n);
    for (auto &[l, r]: a)
        cin >> l >> r;
    ranges::sort(a);
    vi w(n + 1);
    for (int i = 1; i <= n; i++) cin >> w[i];

    int res = -inf;

    vi p;
    auto dfs = [&](auto &self, int m, int x) -> void {
        if (m == 0) {
            priority_queue<int, vi, greater<>> heap;
            int i = 0, ok = 1, sum = 0;
            for (auto pi: p) {
                while (i < n and a[i].first <= pi)
                    heap.push(a[i++].second);
                for (int j = 0; j < pi and ok; j++) {
                    if (not heap.empty() and heap.top() >= pi) heap.pop();
                    else ok = 0;
                }
                if (ok == 0) break;
                sum += w[pi];
            }
            if (ok) res = max(res, sum);
            return;
        }

        for (int y = x; y <= m; y++) {
            p.push_back(y);
            self(self, m - y, y);
            p.pop_back();
        }
    };

    dfs(dfs, n, 1);
    if (res == -inf) cout << "impossible\n";
    else cout << res << "\n";
    return 0;
}

F. Stage: Agausscrab

签到题

#include<bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

const int mod = 1e9 + 7;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    cin >> n;
    vector<string> s(n);
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i] >> a[i];
    }
    string res;
    for (int i = 0, r; i < n; i++) {
        r = 1;
        for (int j = 0; j < n and r <= s.size(); j++) {
            if (a[j] > a[i]) r++;
        }
        while (not s[i].empty() and r > 0)
            s[i].pop_back(), r--;
        res += s[i];
    }
    res[0] = res[0] - 'a' + 'A';
    cout << "Stage: " << res;
    return 0;
}

J. Even or Odd Spanning Tree

首先,可以先求一个最小生成树出来。最小生成树一定是其中一个答案。

然后考虑另一个答案一定是最小生成树换一条边得到的。

下面简单的证明一下。

假设我们必须要换两条边,我们换之前的边是\(a,b\)换之后的是\(x,y\),且\(a < b < x < y\)

则换边后的权值变化了\(x + y - a - b\)。

如果原始的边是一奇一偶,新边一定是同奇或同偶

如果原始的边是同奇或同偶,新边一定是一奇一偶

这样的话,一定可以保证只有一条边与原来的边奇偶不同,因此只换一条边也可满足奇偶变化。

现在这样的组合有\(a \rightarrow x , a \rightarrow y , b \rightarrow x , b \rightarrow y\)

对于\(a\rightarrow x\) 权值的变化是 \(x - a < x + y - a - b\),所以这种情况下换\(a \rightarrow x\) 更优

同理可以推出其他三种。

因此无论什么情况下,均匀换一条边更优的情况出现。

现在我们要考虑的就是选择那两条边。

考虑到,树上删掉任意一条边,均会对联通性发生改变,所以,新边一定和旧边在一个环上。

因此我们可以枚举所有不在最小生成树上的边,然后查找两个端点在树上路径中奇偶性不同且最大边一定是最优的。

查找最大边可以用 lca+树上倍增实现,复杂度\(O(\log n)\),所以整体的复杂度就是\(O(m\log n)\)

#include<bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using edge = array<int, 3>;
using pii = pair<int, int>;
using vi = vector<int>;

const int inf = LLONG_MAX / 2;

class dsu {
private:
    vector<int> fa;
public:
    dsu(int n = 1) {
        fa = vector<int>(n + 1, -1), fa[0] = 0;
    }

    int getfa(int x) {
        if (fa[x] < 0) return x;
        return fa[x] = getfa(fa[x]);
    }

    void merge(int x, int y) {
        x = getfa(x), y = getfa(y);
        if (x == y) return;
        if (fa[x] > fa[y]) swap(x, y);
        fa[x] += fa[y], fa[y] = x;
    }

    bool same(int x, int y) {
        x = getfa(x), y = getfa(y);
        return (x == y);
    }
};

void solve() {
    int n, m;
    cin >> n >> m;
    vector<edge> e(m);
    for (auto &[z, x, y]: e)
        cin >> x >> y >> z;


    ranges::sort(e);
    vector<vector<pii>> mst(n + 1);
    vector<edge> ne;
    dsu d(n);
    int sum = 0, cnt = 0;
    for (auto &[w, x, y]: e) {
        if (d.same(x, y)) ne.push_back({w, x, y});
        else {
            sum += w, d.merge(x, y), cnt++;
            mst[x].emplace_back(y, w);
            mst[y].emplace_back(x, w);
        }
    }
    if (cnt != n - 1) {
        cout << "-1 -1\n";
        return;
    }

    e = move(ne);
    int dn = 0, lg2N = log2(n);
    vector<int> dfn(n + 1), dep(n + 1);
    vector<vi> f(n + 1, vi(lg2N + 1));
    vector<vi> fa(n + 1, vi(lg2N + 1));
    vector edgeMax(2, vector(n + 1, vi(lg2N + 1)));

    for (int t = 0; t < 2; t++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= lg2N; j++) {
                if (edgeMax[t][i][j] == 0) continue;
                assert(edgeMax[t][i][j] % 2 == t);
            }
        }
    }

    auto dfs = [&](auto &&self, int x, int ff) -> void {
        f[dfn[x] = ++dn][0] = ff;
        for (auto [y, w]: mst[x]) {
            if (y == ff) continue;
            fa[y][0] = x, dep[y] = dep[x] + 1;
            edgeMax[w & 1][y][0] = w;
            self(self, y, x);
        }
    };

    auto get = [&](int x, int y) -> int {
        if (dfn[x] < dfn[y]) return x;
        return y;
    };

    auto lca = [&](int u, int v) -> int {
        if (u == v) return u;
        u = dfn[u], v = dfn[v];
        if (u > v) swap(u, v);
        int d = log2(v - u++);
        return get(f[u][d], f[v - (1 << d) + 1][d]);
    };

    dep[1] = 1;
    dfs(dfs, 1, 0);
    for (int i = 1; i <= lg2N; i++)
        for (int j = 1; j + (1 << i) - 1 <= n; j++)
            f[j][i] = get(f[j][i - 1], f[j + (1 << i - 1)][i - 1]);


    for (int i = 1; i <= lg2N; i++)
        for (int j = 1; j <= n; j++) {
            fa[j][i] = fa[fa[j][i - 1]][i - 1];
            for (int t = 0; t < 2; t++)
                edgeMax[t][j][i] = max(edgeMax[t][j][i - 1], edgeMax[t][fa[j][i - 1]][i - 1]);
        }


    auto query = [&](int w, int x, int y) -> int {
        int z = lca(x, y), res = -1;
        for (int i = lg2N; i >= 0 and x != z; i--) {
            if (dep[fa[x][i]] < dep[z]) continue;
            res = max(res, edgeMax[w][x][i]);
            x = fa[x][i];
        }
        for (int i = lg2N; i >= 0 and y != z; i--) {
            if (dep[fa[y][i]] < dep[z]) continue;
            res = max(res, edgeMax[w][y][i]);
            y = fa[y][i];
        }
        return res;
    };

    int res = inf;
    for (auto [w, x, y]: e) {
        auto t = query((w % 2) ^ 1, x, y);
        if (t <= 0) continue;
        res = min(res, sum - t + w);
    }

    if (res == inf) res = -1;
    if (sum & 1) cout << res << " " << sum << "\n";
    else cout << sum << " " << res << "\n";
    return;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}

M. Triangles

一个比较有意思的数学题。

首先要打表找规律,在不删除线的情况下,三角形的数目是\(\frac{n(n + 2 )(2n + 1)}{8}\)

然后考虑删掉横线在哪些三角形里面。

我们考虑顶点在上的情况。

我们可以枚举出底边的左端点\(i\)和长度\(x\),枚举左端点\([1,b]\)范围内。

然后右端点自然就是\(i+x\),那么\(i+x\)要满足\(b + 1 \le i+x \le a\)

在考虑顶点,顶点是在\(a - x\)行,那么$ 0\le a-x \le a - 1$

因此联立两个方程,可得$ \max(1, b - i + 1 ) \le x \le \min(a , a-i + 1)$;

考虑顶点在下的情况,我们枚举右端点\(i\)长度\(x\),类比可得到\(\max ( 1 , i - b )\le x \le \min(n - a, i - 1)\)

满足上述条件的\(x\)均成立,因此我们可以\(O(1)\)的计算出每个\(i\)的贡献

#include<bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    i64 n, a, b;
    cin >> n >> a >> b;
    i64 sum = n * (n + 2) * (2 * n + 1) / 8;
    for (i64 i = 1; i <= b; i++) {
        i64 l = max(1ll, b - i + 1), r = min(a, a - i + 1);
        if (l <= r) sum -= r - l + 1;
    }
    for (i64 i = b + 1; i <= a + 1; i++) {
        i64 l = max(1ll, i - b), r = min(n - a, i - 1);
        if (l <= r) sum -= r - l + 1;
    }
    cout << sum;
    return 0;
}

标签:return,int,res,Universal,Cangqian,fa,vector,using,Stage
From: https://www.cnblogs.com/PHarr/p/18408728

相关文章

  • The 3rd Universal Cup. Stage 8: Cangqian
    题解:https://files.cnblogs.com/files/clrs97/ZJCPC24_Tutorial.pdf Code:A.Bingo#include<bits/stdc++.h>usingnamespacestd;stringn;intm;typedeflonglongll;llsum[1000005];intpw[1000005];boolall[1000005];intsol[1000020];voidsolv()......
  • vue项目利用git commit 触发执行 eslint检查,使用husky 和 lint-staged
    lint-staged安装和使用说明lint-staged是一个插件,为了方便触发eslint,配置哪些文件触发eslintstylelint等安装yarnaddlint-staged创建.lintstagedrc在根目录{"*.vue":"eslint","*.ts":"eslint","*.tsx":"eslint&quo......
  • The 2023 ICPC Asia Nanjing Regional Contest (The 2nd Universal Cup. Stage 11: Na
    C-PrimitiveRoot题意给定p与m(p为质数),已知(g^(P-1))%P==1且g<=m。求g的个数。思路由(g^(P-1))%P==1与异或性质a-b<=a^b<=a+b,可以推出g=((k*p+1)^(p-1))与p*(k-1)+2<=g<=p*(k+1)。又因为g<=m,则当p*(k+1)<=......
  • ServiceStage集成Sermant实现应用的优雅上下线
    作者:聂子雄华为云高级软件工程师摘要优雅上下线旨在确保服务在进行上下线操作时,能够平滑过渡,避免对业务造成影响,保证资源的高效利用。Sermant基于字节码增强的技术实现了应用优雅上下线能力,应用发布与运维平台ServiceStage通过集成Sermant使得应用在进行持续发布时实现无侵入式地......
  • The 1st Universal Cup. Stage 8: Slovenia
    Preface这场其实是昨天打的,但因为今天没训练就摆烂拖到今天才补题和写博客这场题感觉都挺可做的,但前期出题有点慢导致后期没时间了,徐神和祁神赛后20min过了J有点可惜A.Bandits题都没看,不做评价B.CombinationLocks不难发现这题本质就是在0/1串上操作,每次移动到另......
  • Photomator 3.3.22 (macOS Universal) - 照片编辑软件
    Photomator3.3.22(macOSUniversal)-照片编辑软件适用于Mac、iPhone和iPad的终极照片编辑器请访问原文链接:https://sysin.org/blog/photomator/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgPhotomator适用于Mac、iPhone和iPad的终极照片编辑器。P......
  • The 3rd Universal Cup. Stage 7- Warsaw
    B.MissingBoundaries给\(N\)个区间,可能存在一些区间的端点不确定。现在你要指定区间的端点,是否可以使得所有不重不漏的覆盖\([1,L]\)首先考虑两个端点都确定的区间,两两之间应该不相交。考虑只有一个端点的区间,对于已经被确定的点,一定不能是在已被覆盖的区间内。其次所有的......
  • The 1st Universal Cup. Stage 7: Zaporizhzhia
    Preface在寝室白兰了一周多后也是终于等到徐神归来开始训练了这场的题感觉比较偏数学了,感觉和之前打的一个Tokyo的OpenCup很像,因此后期挺坐牢的4h左右堪堪写出7题,最后全队RushD结果发现暴力打表都打错了,怎么回事呢A.SquareSum这题在去年暑假前集训数学专题中......
  • [Paper Reading] One-Stage 3D Whole-Body Mesh Recovery with Component Aware Trans
    One-Stage3DWhole-BodyMeshRecoverywithComponentAwareTransformerlink时间:CVPR2023机构:粤港澳大湾区数字经济研究院(IDEA)&&清华大学深圳国际研究生院TL;DR使用一个纯Transformer结构模型(名为OSX)直接预测Body/Hand/Face的参数,避免了之前各模型分开预测后融合复......
  • SRL_STAGES_TO_REG_INPUT
    寄存器级可以通过SLR输入拉出,也可以使用SRL_STAGES_TO_REG_INPUT属性。这提供了对流水线寄存器结构的控制,以在流水线下和流水线上寻址SRL基元的输入侧。架构支持所有架构。适用对象•单元格(get_cell)作为叶级SRL实例。价值观•1:Vivado逻辑优化将从指定的SRL中提取寄存......