ABC210 D、E、F题解 haven't finish -- F

D

不难的。
两个点的的关系要么是左上-右下,要么是左下-右上,然后拆绝对值(这是拆绝对值的很经典做法),用个前缀最小值维护即可。
值得一提的是,若这题要求在线做,需要用线段树/树状数组/二维线段树/二维树状数组。

E

这题本质上是求 \(n\) 个点的最小生成树,但由于 \(nm\leq 10^{14}\),所以不能直接跑,但是我们可以让边按权值排序。考虑 \(j\) 什么时候会被 \(i\) 连,令当前执行完 \(k\) 次操作,则 \(j=(i+t_1\times a[1]+t_2\times a[2]... + t_k\times a[k])\mod n\)\(t_1,t_2..t_k\) 为常数,可为负)。
看着 \(mod\) 不爽,柿子可化为 \(j=i+t_1\times a[1]+t_2\times a[2]... + t_k\times a[k] + t_n \times n\)
这个东西由裴蜀定理得 \(j\equiv i (mod\ gcd(a[1],a[2],...,a[k],n))\)。所以执行完 \(k\) 次操作后剩下 \(gcd\) 个联通块(因为每次 \(i\) 会和 \(i+gcd\) 连),联立上一个 \(gcd_{last}\),相减就得到了此时连了几条边(这个 trick 经常会用到)。最后当 \(gcd\neq 1\) 时输出 \(-1\)

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define LL long long
using namespace std;
const int MAXN = 1e5 + 5;
struct Node {
	int X, Y;
	bool operator < (const Node P) const { return Y < P.Y; }
}arr[MAXN];
int n, m, las;
LL ans, gcd_;
int Gcd(int x, int y) { return y ? Gcd(y, x % y) : x; }
int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i ++) scanf("%d%d", &arr[i].X, &arr[i].Y);
	sort(arr + 1, arr + 1 + m); las = n;
	for(int i = 1; i <= m; i ++) gcd_ = Gcd(las, arr[i].X), ans += (LL)(las - gcd_) * arr[i].Y, las = gcd_;
	if(gcd_ != 1) ans = -1;
	printf("%lld", ans);
	return 0;
}

F

听说是 2-sat,正在学,,

posted @ 2021-07-20 15:03  Saintex  阅读(71)  评论(0编辑  收藏  举报