翻开以前打的 #583,水平不够场上只过了五题。最近来补一下题,来记录我sb的调试过程。

估计我这个水平现场也过不了,因为前面的题已经zz调了好久……


F:就是给你环上一些点,两两配对求距离最小值。

匹配边明显是不能交叉的啊。那就直接转一个环就好了。

考虑计算贡献,盲猜一个点的贡献方向改变不会特别多,观看题解以验证,证明一发,发现猜对了。

很明显,考虑 \(x \leq y\),那么固定 \(y\),一定有一个分界点,使得 \(y - x > m - x + y\)。

开一个长度为 \(n\) 的数组,表示转 \(\frac{2 \pi i}{n}\)。

所以对于每个点计算一下贡献,对于一个连续段贡献相同,直接差分前缀和就行。

边界还是要仔细考虑的,也就是 \(y - x = m - x + y\) 的时候。分别考虑两个环贡献,具有对偶性,那么写成一个函数时就要注意边界。

细节也不多,过了样例就A了。

#include <bits/stdc++.h>

const int MAXN = 200010;
typedef long long LL;
int n, R;
struct node {
LL at; int id;
bool operator < (node b) const { return at < b.at; }
} as[MAXN], bs[MAXN];
int ansl[MAXN];
LL pre1[MAXN], pre2[MAXN], * pre;
void _mkadd(int l, int r, int v) {
pre[l] += v, pre[r + 1] -= v;
}
void mkadd(int l, int r, int v, int dta) {
if (l >= r) return ;
--r;
l = (l - 1 - dta + n) % n + 1;
r = (r - 1 - dta + n) % n + 1;
if (l <= r) _mkadd(l, r, v);
else _mkadd(1, r, v), _mkadd(l, n, v);
}
void pusharr(int at, node * dst, int dta) {
node * it;
if (dst == bs)
it = std::lower_bound(dst + 1, dst + 1 + n, (node) {at << 1, 0});
else
it = std::upper_bound(dst + 1, dst + 1 + n, (node) {at << 1, 0});
node * lhs = std::upper_bound(dst + 1, it, (node) {2 * at - R, 0});
node * rhs = std::lower_bound(it, dst + 1 + n, (node) {2ll * at + R, 0});
const int delta = (dst != as) * R;
mkadd(1, lhs - dst, delta - at, dta);
mkadd(lhs - dst, it - dst, at, dta);
mkadd(it - dst, rhs - dst, -at, dta);
mkadd(rhs - dst, 1 + n, delta + at, dta);
}
int main() {
std::ios_base::sync_with_stdio(false), std::cin.tie(0);
std::cin >> R >> n;
for (int i = 1; i <= n; ++i) as[i].id = i, std::cin >> as[i].at;
for (int i = 1; i <= n; ++i) bs[i].id = i, std::cin >> bs[i].at;
std::sort(as + 1, as + 1 + n);
std::sort(bs + 1, bs + 1 + n);
for (int i = 1; i <= n; ++i) as[i].at <<= 1, bs[i].at <<= 1;
for (int i = 1; i <= n; ++i) {
pre = pre1, pusharr(as[i].at >> 1, bs, i - 1);
pre = pre2, pusharr(bs[i].at >> 1, as, i - 1);
}
LL ans = 0x3f3f3f3f3f3f3f3fLL; int at = 1;
for (int i = 1; i <= n; ++i)
pre1[i] += pre1[i - 1], pre2[i] += pre2[i - 1];
for (int i = 1; i <= n; ++i) {
LL now = pre1[i] + pre2[i > 1 ? n - i + 2 : 1];
if (now < ans) ans = now, at = i;
}
for (int i = 1; i <= n; ++i)
ansl[as[i].id] = bs[(i + at - 2) % n + 1].id;
std::cout << ans << std::endl;
for (int i = 1; i <= n; ++i)
std::cout << ansl[i] << ' ';
std::cout << std::endl;
return 0;
}

G:询问是否存在一个矩形的四个顶点,对角相等,邻边相反的点,带一行的区间修改。

看到数据范围,\(m \times Q = 10^9\),自然 bitset。但是怎么维护呢?

考虑两行,记 \(A\) 为其中一行 \(1\) 出现的位置, \(B\) 是另一行的 \(1\),所有位置(全集)就是 \(U\)。

那么就是 \(A \cap \left(U \backslash B\right)\) 和 \(B \cap \left(U \backslash A\right)\) 都非空,这个判定函数记为 \(f(A, B) = [A \cap \left(U \backslash B \right) \neq \emptyset][B \cap \left(U \backslash A \right) \neq \emptyset]\)。

根据题解,\(\neg f\left(A,B\right)\) 具有传递性。其实这个是集合包含啦,如果两个集合互不包含,就会有解。(我太菜没从上面想到包含关系)

那么显然无解时包含关系形成了一条链。我们直接按集合大小排序,然后维护相邻不包含关系的集合即可。

手写bitset写挂……貌似效率还没stl高。

#include <bits/stdc++.h>

const int MAXN = 2000;
typedef long long LL;
int n, m, Q;
const int dig = 2048 / 64;
struct bitset {
LL A[dig]; int ppc;
bool contains(const bitset & b) const {
for (int i = 0; i != dig; ++i)
if ((A[i] & b.A[i]) != b.A[i])
return false;
return true;
}
void rev(int l, int r) {
for (int i = (l >> 6); i <= (r >> 6); ++i)
ppc -= __builtin_popcountll(A[i]);
A[l >> 6] ^= ((1ll << (l & 63)) - 1) ^ -1;
A[r >> 6] ^= (r & 63) == 63 ? -1 : (1ll << ((r & 63) + 1)) - 1;
(l >> 6) == (r >> 6) ? (A[l >> 6] ^= -1) : 0;
for (int i = (l >> 6) + 1; i < (r >> 6); ++i) A[i] ^= -1;
for (int i = (l >> 6); i <= (r >> 6); ++i)
ppc += __builtin_popcountll(A[i]);
}
int ctzofandinvb(const bitset & b) {
for (int i = 0; i != dig; ++i) {
LL now = A[i] & ~b.A[i];
if (now) return i << 6 | __builtin_ctzll(now);
}
return -1;
}
} mat[MAXN];
typedef std::pair<int, int> PII;
std::set<PII> S, diff;
int getsuc(std::set<PII>::iterator it) {
return ++it != S.end() ? it -> second : -1;
}
int getpre(std::set<PII>::iterator it) {
return it != S.begin() ? (--it) -> second : -1;
}
void ins(int a, int b) {
if (a == -1 || b == -1) return ;
if (!mat[b].contains(mat[a]))
diff.insert(PII(a, b));
}
void del(int a, int b) {
if (a == -1 || b == -1) return ;
diff.erase(PII(a, b));
}
bitset t;
int main() {
std::ios_base::sync_with_stdio(false), std::cin.tie(0);
std::cin >> n >> m >> Q;
for (int i = 0; i < n; ++i) S.insert(PII(0, i));
int t1, t2, t3;
while (Q --> 0) {
std::cin >> t1 >> t2 >> t3; --t1, --t2, --t3;
auto t = S.find(PII(mat[t1].ppc, t1));
int suc = getsuc(t), pre = getpre(t);
del(pre, t1); del(t1, suc);
S.erase(t); mat[t1].rev(t2, t3);
auto at = S.insert(PII(mat[t1].ppc, t1)).first;
int ts = getsuc(at), tp = getpre(at);
del(tp, ts);
ins(tp, t1); ins(t1, ts);
if (ts != suc && tp != pre) ins(pre, suc);
if (diff.empty()) std::cout << "-1\n";
else {
PII t = *diff.begin();
int x1 = t.first, x2 = t.second;
int y1 = mat[x1].ctzofandinvb(mat[x2]);
int y2 = mat[x2].ctzofandinvb(mat[x1]);
if (x1 > x2) std::swap(x1, x2);
if (y1 > y2) std::swap(y1, y2);
++x1, ++x2, ++y1, ++y2;
std::cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\n';
}
}
return 0;
}

H:给树 \(K\) 染色,使得所有长为 \(K\) 的路径恰好包含所有 \(K\) 种颜色。

一道简单题,但我挂了一堆 sb 地方

显然,应该找出直径来。然后直径上插入一些子树,根据在直径上的位置调整颜色。颜色就从上往下按顺序分配。

有了这个,我们考虑无解情况:

如果在直径上,从左边和右边都能下来,那么直径必须回文。

所以先特判掉 \(K = 2\) 的情况,剩下直径肯定不回文。

乍一看这个判定太弱了。我们考虑颜色分配,祖先链分配下来分叉成两个子树,两个子树的链又能拼成长度为 \(K\) 的链,那这链必须存在回文,必定无解。

也就是存在一个点,往三个方向 \(A, B, C\),\(AB, BC, AC\) 三个方向的链长度都大于等于 \(K\)。

那么最后的问题就是考虑直径上怎么下去了。

如果能从右边下来,那么编号分配的 \(delta = -1\),否则就是 \(1\)。

据说我直径求完没加 \(1\) 导致少一个点,还有 dp 时在根加入了没用的子树导致 \(No\) 判挂,取模有两处应该写 \(K\) 结果写了 \(R\)……

实际上细节不多。

#include <bits/stdc++.h>

const int MAXN = 200010;
void bye() { std::cout << "No\n"; exit(0); }
int head[MAXN], nxt[MAXN << 1], to[MAXN << 1], tot;
void addedge(int b, int e) {
nxt[++tot] = head[b]; to[head[b] = tot] = e;
nxt[++tot] = head[e]; to[head[e] = tot] = b;
}
int ansl[MAXN];
int n, K;
void simpledfs(int u, int fa = 0, int col = 1) {
ansl[u] = col;
for (int i = head[u]; i; i = nxt[i])
if (to[i] != fa)
simpledfs(to[i], u, col ^ 1);
}
int dis[MAXN];
void dfsx(int u, int fa = 0) {
for (int i = head[u]; i; i = nxt[i])
if (to[i] != fa) {
dis[to[i]] = dis[u] + 1;
dfsx(to[i], u);
}
}
const int INF = 0x3f3f3f3f;
struct data {
int a[3];
data() { a[0] = a[1] = a[2] = -INF; }
void insert(int x) {
if (x >= a[0]) a[2] = a[1], a[1] = a[0], a[0] = x;
else if (x >= a[1]) a[2] = a[1], a[1] = x;
else if (x >= a[2]) a[2] = x;
}
void shift() { ++a[0], ++a[1], ++a[2]; }
} val[MAXN], vt[MAXN];
void dfs1(int u, int fa = 0) {
for (int i = head[u]; i; i = nxt[i])
if (to[i] != fa) {
dfs1(to[i], u);
val[u].insert(std::max(val[to[i]].a[0], 0) + 1);
}
}
void dfs2(int u, int fa = 0, int upv = 0) {
for (int i = head[u]; i; i = nxt[i])
if (to[i] != fa) {
int tv = std::max(upv, val[u].a[val[to[i]].a[0] + 1 == val[u].a[0]]) + 1;
dfs2(to[i], u, tv);
}
vt[u] = val[u]; if (fa) vt[u].insert(upv);
if (vt[u].a[2] + vt[u].a[1] + 1 >= K) bye();
}
int li[MAXN], inc[MAXN];
bool mark(int u, int dst, int fa = 0) {
if (u == dst) {
li[dis[u]] = u;
return true;
}
for (int i = head[u]; i; i = nxt[i])
if (to[i] != fa) {
if (mark(to[i], dst, u)) {
li[dis[u]] = u;
return true;
}
}
return false;
}
int R;
void dfsmk(int u, int fa, int now, int delta) {
now = (now + delta) % K;
ansl[u] = now;
for (int i = head[u]; i; i = nxt[i])
if (to[i] != fa)
dfsmk(to[i], u, now, delta);
}
int main() {
std::ios_base::sync_with_stdio(false), std::cin.tie(0);
std::cin >> n >> K;
for (int i = 1, t1, t2; i < n; ++i) {
std::cin >> t1 >> t2;
addedge(t1, t2);
}
if (K == 2) simpledfs(1);
else {
dfs1(1); dfs2(1);
dis[1] = 0; dfsx(1);
int at = 1, rt;
for (int i = 2; i <= n; ++i) if (dis[i] > dis[at]) at = i;
dis[at] = 0; dfsx(rt = at);
at = 1;
for (int i = 2; i <= n; ++i) if (dis[i] > dis[at]) at = i;
R = dis[at] + 1;
mark(rt, at);
for (int i = 0; i < R; ++i) inc[li[i]] = true;
for (int i = 0; i < R; ++i) {
ansl[li[i]] = i % K;
int dta = R - 1 - i > i ? K - 1 : 1;
for (int j = head[li[i]]; j; j = nxt[j])
if (!inc[to[j]])
dfsmk(to[j], li[i], i, dta);
}
}
std::cout << "Yes" << std::endl;
for (int i = 1; i <= n; ++i) std::cout << ansl[i] + 1 << ' ';
std::cout << std::endl;
return 0;
}

Codeforces 1214 F G H 补题记录的更多相关文章

  1. Codeforces Round #786 (Div. 3) 补题记录

    小结: A,B,F 切,C 没写 1ll 对照样例才发现,E,G 对照样例过,D 对照样例+看了其他人代码(主要急于看后面的题,能调出来的但偷懒了. CF1674A Number Transforma ...

  2. Codeforces Round #617 (Div. 3) 补题记录

    1296A - Array with Odd Sum 题意:可以改变数组中的一个数的值成另外一个数组中的数,问能不能使数组的和是个奇数 思路:签到,如果本来数组的和就是个奇数,那就OK 如果不是,就需 ...

  3. Codeforces Round #615 (Div. 3) 补题记录

    第一次搞CF,结果惨不忍睹...还是太菜了 A:要用到全部的钱,所以总数必须是3的倍数,而且初始状态下任意一人的钱数不能超过总数除以3,否则没法分了 (也就这个签到算是在我能力范围之内了....) # ...

  4. 【cf补题记录】Codeforces Round #608 (Div. 2)

    比赛传送门 再次改下写博客的格式,以锻炼自己码字能力 A. Suits 题意:有四种材料,第一套西装需要 \(a\).\(d\) 各一件,卖 \(e\) 块:第二套西装需要 \(b\).\(c\).\ ...

  5. 【cf补题记录】Codeforces Round #607 (Div. 2)

    比赛传送门 这里推荐一位dalao的博客-- https://www.cnblogs.com/KisekiPurin2019/ A:字符串 B:贪心 A // https://codeforces.c ...

  6. 【补题记录】ZJU-ICPC Summer Training 2020 部分补题记录

    补题地址:https://zjusummer.contest.codeforces.com/ Contents ZJU-ICPC Summer 2020 Contest 1 by Group A Pr ...

  7. Codeforces Round #419 (Div. 1) 补题 CF 815 A-E

    A-C传送门 D Karen and Cards 技巧性很强的一道二分优化题 题意很简单 给定n个三元组,和三个维度的上限,问存在多少三元组,使得对于给定的n个三元组中的每一个,必有两个维度严格小于. ...

  8. ZJUT11 多校赛补题记录

    牛客第一场 (通过)Integration (https://ac.nowcoder.com/acm/contest/881/B) (未补)Euclidean Distance (https://ac ...

  9. 【JOISC 2020 补题记录】

    目录 Day 1 Building 4 Hamburg Steak Sweeping Day 2 Chameleon's Love Making Friends on Joitter is Fun R ...

随机推荐

  1. 【Havel 定理】Degree Sequence of Graph G

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2454 [别人博客粘贴过来的] 博客地址:https://www.cnblogs.com/debug ...

  2. golang作用域问题

    //参考 https://segmentfault.com/a/1190000012214571 //参考 https://studygolang.com/articles/2215 func bar ...

  3. 并不对劲的复健训练-bzoj5249:loj2472:p4364[2018多省联考]IIIDX

    题目大意 给出\(n,k,d_1,...,d_n\)(\(n\leq 5\times 10^5,1<k\leq 10^9,d\leq 10^9,k\in R\)).有一个满足 对于每个点\(i\ ...

  4. 并不对劲的bzoj1972:loj2885:p2482[SDOI2010]猪国杀

    题目大意 只能放链接了. 题目中有一点没说:并不是保证牌够用,而是在牌不够用时反复抽最后一张牌. 题解 发现玩家的数量比较少,所以可以不太在意时间够不够用. 考虑三件事:1.基本操作,如摸牌.出牌.玩 ...

  5. TreeSet——实现Comparable接口并重写CompareTo()方法

    TreeSet是以自然顺序存的数据,例如 Set<Student> students=new TreeSet(); students.add(new Student("111&q ...

  6. C#Linq之求和,平均值,最大值,最小值

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  7. Flask:上下文管理

    1. werkzurg from werkzur.serving import run_simple def run(environ,start_response): reuturn [b'hello ...

  8. Oracle数据库中的变量

    Oracle数据库中的变量 来源:https://blog.csdn.net/wahaa591/article/details/46772769 1.define(即host变量) define va ...

  9. jvm自带的监控机制

    Jdk为我们提供了查看java服务运行时的监控情况 1.如下图所示,打开指定目录下的jconsole.exe应用程序文件. 2.双击后跳出如下界面,可以看到,我们可以监视本地的,也可以监视远程服务.本 ...

  10. JavaScript使用纯函数避免bug

    纯函数 一.纯函数 定义:纯函数是指不依赖并且不修改其作用域之外的函数.通过以下几个示例来认识纯函数: var a = 10; //纯函数 function foo(num){ return num ...