惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - 聂微东
F
Fortinet All Blogs
H
Help Net Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
DataBreaches.Net
MyScale Blog
MyScale Blog
B
Blog
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
IT之家
IT之家
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
博客园_首页
L
LangChain Blog
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky

某岛

AtCoder Beginner Contest 409 Luogu P5325. 【模板】Min_25 筛 UOJ #188. 【UR #13】Sanrd AtCoder Beginner Contest 371 AtCoder Beginner Contest 369 RPGMaker 2k3 百科 OneShot 的考古 2024“开创拓芯”游戏创享节的相关记录 CJ 回来后的戒断反应 Luogu P10221. [省选联考 2024] 重塑时光 Luogu P5308 [COCI2018-2019#4] Akvizna wqs 二分 歌唱王国 Lean 相关 BZOJ 3153. Sone1 The 2023 ICPC World Finals Luxor 新巴别塔 Sora 的想象与思考 Facebook Hacker Cup 2023 Round 1 AtCoder Beginner Contest 322 LLaMA 2 相关 HuggingFace AI Game Jam ACL 2023 Trans 相关… Luogu P2053. [SCOI2007] 修车 Luogu P1973. [NOI2011] NOI 嘉年华 Luogu P1933. [NOI2010] 旅行路线 Luogu P1954. [NOI2010] 航空管制 Luogu P2048. [NOI2010] 超级钢琴 Luogu P2046. [NOI2010] 海拔
Codeforces Round #875
2023-05-29 · via 某岛

久违地冲了一局。。。无悬念的差点爆 0 了。

Problem A. Copil Copac Draws Trees

题意:给定一个树,和边,初始根节点是点亮的,每回合你可以按照边地顺序扫一遍所有边,如果其中一个点是点亮的,那么点亮另一个点。问多少回合后所有点被点亮。

分析:显然不考虑边顺序的话,就是求树的深度,这个过程也可以看作树 dp。。
dp[i] 存两个值,分别表示最少被点亮所需的回合数,和被点亮时所用边的编号。转移的时候讨论一下编号即可。

Problem C. Hyperregular Bracket Strings

题意:问有多少长度 n 的合法括号序列,满足给定的所有区间也时合法的括号序列。

分析:个人感觉非常棒的题目。首先不考虑区间的话就是卡塔兰数 {C_i}。

然后考察 [1,4] [2,3] 和 [1,3] [2,4] 两种情况,前者比较容易分析,[2,3] 现在一定是一个独立的合法括号序列,[1]-[4] 然后两个位置虽然不连续,但是也构成一个独立的合法括号序列。而后者 [2,3] 则要求 [1] [2,3] [4] 分别是三组独立的卡塔兰序列,因为中间重合的部分对前缀和的 delta 一定是 0(反证法)。

这样看的话最后结果一定是若干 {C_i} 相乘,难点就是分解出这些独立的区间的测度,看起来结构简单,写起来却并不容易,我们无法像表达式解析那样简单的递归或者用一个栈,考虑到还有区间共享端点的情况就更麻烦了。

然后有一个非常巧妙地思路。。。给每个区间随机分配一个 uint 数,然后把前缀和改成 xor 前缀和,然后用 hash[] 记录每种区间集合影响下的测度数,就能轻易处理不连续的状态,并区分上面说到的嵌套和重叠两种情况了。

这种 hash 的思想非常实用,比如去年 FHQ R2 的 A 题 也出现过类似的思路。

具体说来就是开三个东西:

map<int, uint64_t> H; // 记录每个区间的随机 hash 映射
map<uint64_t, int> cnt; // 记录每个区间交的格子数
uint64_t S[N]; // 记录前缀和对应的区间交

如果区间稀疏的话,还需要对前缀和离散化。

#include <lastweapon/poly>
#include <bits/stdc++.h>
using namespace lastweapon;

mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<uint64_t> rnd(0, ULLONG_MAX);

const int N = int(3e5) + 9;
Mint C[N]; uint64_t S[N];
int n, k;

Mint binom(int n, int m) {
    return fac[n] * invFac[m] * invFac[n-m];
}

map<int, uint64_t> H;
map<uint64_t, int> cnt;
uint64_t h(int x) {
    if (!CTN(H, x)) H[x] = rnd(gen);
    return H[x];
}

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    FOR(i, 1, N/2) C[i*2] = binom(2*i,  i) - binom(2*i, i+1);

    Rush {
        RD(n, k);

        H.clear(), cnt.clear(); fill(S+1, S+n+1, 0);

        REP(i, k) {
            int a, b; RD(a, b);
            S[a] ^= h(i); S[b+1] ^= h(i);
        }

        REP_1(i, n) ++cnt[S[i] ^= S[i-1]];
        Mint z = 1; for (auto it: cnt) z *= C[it.se];

        cout << z << endl;
    }
}

Posted by xiaodao
Category: 日常