首页 > 其他分享 >AtCoder Beginner Contest 163 F path pass i

AtCoder Beginner Contest 163 F path pass i

时间:2023-05-12 20:15:07浏览次数:39  
标签:AtCoder typedef Beginner Contest long maxn define

洛谷传送门

AtCoder 传送门

感觉我的做法比较奇葩(

容斥,总路径数减去只走点权为 \(k\) 的路径。设点权为 \(k\) 的点数为 \(c_k\),点权不为 \(k\) 的点构成的每个连通块大小为 \(s_i\),那么 \(ans_k = \frac{n(n-1)}{2} - \sum \frac{s_i (s_i - 1)}{2} + c_k\)。

考虑快速计算 \(\sum \frac{s_i (s_i - 1)}{2}\),考虑线段树分治,每条边 \((u,v)\) 当 \(k \ne a_u \land k \ne a_v\) 是有用的,把它插入对应结点,然后直接上可撤销并查集维护即可。

复杂度 \(O(n \log^2 n)\)。

code
// Problem: F - path pass i
// Contest: AtCoder - AtCoder Beginner Contest 163
// URL: https://atcoder.jp/contests/abc163/tasks/abc163_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

ll n, a[maxn], fa[maxn], rnk[maxn], cnt, top, ans, sz[maxn], b[maxn], c[maxn];
pair<ll*, ll> stk[maxn * 10];
vector<pii> tree[maxn << 2];

int find(int x) {
	return fa[x] == x ? x : find(fa[x]);
}

inline void merge(int x, int y) {
	x = find(x);
	y = find(y);
	if (x == y) {
		return;
	}
	stk[++top] = make_pair(&cnt, cnt);
	--cnt;
	stk[++top] = make_pair(&ans, ans);
	if (rnk[x] <= rnk[y]) {
		stk[++top] = make_pair(fa + x, fa[x]);
		fa[x] = y;
		ans += sz[x] * (sz[x] - 1) / 2;
		ans += sz[y] * (sz[y] - 1) / 2;
		stk[++top] = make_pair(sz + y, sz[y]);
		sz[y] += sz[x];
		ans -= sz[y] * (sz[y] - 1) / 2;
		if (rnk[x] == rnk[y]) {
			stk[++top] = make_pair(rnk + y, rnk[y]);
			++rnk[y];
		}
	} else {
		stk[++top] = make_pair(fa + y, fa[y]);
		fa[y] = x;
		ans += sz[x] * (sz[x] - 1) / 2;
		ans += sz[y] * (sz[y] - 1) / 2;
		stk[++top] = make_pair(sz + x, sz[x]);
		sz[x] += sz[y];
		ans -= sz[x] * (sz[x] - 1) / 2;
	}
}

inline void undo() {
	*stk[top].fst = stk[top].scd;
	--top;
}

void update(int rt, int l, int r, int ql, int qr, pii x) {
	if (ql > qr) {
		return;
	}
	if (ql <= l && r <= qr) {
		tree[rt].pb(x);
		return;
	}
	int mid = (l + r) >> 1;
	if (ql <= mid) {
		update(rt << 1, l, mid, ql, qr, x);
	}
	if (qr > mid) {
		update(rt << 1 | 1, mid + 1, r, ql, qr, x);
	}
}

void dfs(int rt, int l, int r) {
	int lsttop = top;
	for (pii p : tree[rt]) {
		merge(p.fst, p.scd);
	}
	if (l == r) {
		b[l] = ans;
	} else {
		int mid = (l + r) >> 1;
		dfs(rt << 1, l, mid);
		dfs(rt << 1 | 1, mid + 1, r);
	}
	while (top > lsttop) {
		undo();
	}
}

void solve() {
	scanf("%lld", &n);
	ans = n * (n - 1) / 2;
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		++c[a[i]];
		fa[i] = i;
		sz[i] = 1;
		rnk[i] = 1;
	}
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		if (a[u] > a[v]) {
			swap(u, v);
		}
		pii e = make_pair(u, v);
		update(1, 1, n, 1, a[u] - 1, e);
		update(1, 1, n, a[u] + 1, a[v] - 1, e);
		update(1, 1, n, a[v] + 1, n, e);
	}
	dfs(1, 1, n);
	for (int i = 1; i <= n; ++i) {
		printf("%lld\n", b[i] + c[i]);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,typedef,Beginner,Contest,long,maxn,define
From: https://www.cnblogs.com/zltzlt-blog/p/17396172.html

相关文章

  • AtCoder Beginner Contest 207 F Tree Patrolling
    洛谷传送门AtCoder传送门简单树形dp。设\(f_{u,i,p=0/1,q=0/1}\)为\(u\)的子树中被覆盖点数为\(i\),\(u\)有没有被覆盖,\(u\)有没有被选。转移树形背包合并即可,需要分类讨论。要注意如果\(u\)没被覆盖,\(v\)选了,或者\(u\)选了,\(v\)没被覆盖,被覆盖点数要\(+1\)。......
  • AtCoder Beginner Contest 177 F I hate Shortest Path Problem
    洛谷传送门AtCoder传送门设\(f_{i,j}\)为从第\(1\)行到\((i+1,j)\)的最短路。因为我们并不关心最后到达的是哪一个格子,于是强制\(f_{i,j}\)为必须从\((i,j)\)往下走一格到\((i+1,j)\)的最短路。有转移:\[f_{i,r+1}\getsf_{i-1,j}+r+2-j,j\in[l......
  • AtCoder Beginner Contest 152 A-E
    AtCoderBeginnerContest152A-ACorWAvoidsolve(){intn=read(),m=read();puts(n==m?"Yes":"No");}B-ComparingStringsvoidsolve(){intn=read(),m=read();if(m<n)swap(n,m);for(inti=1;i<=m;i++){......
  • 21st UESTC Programming Contest - Preliminary except BCGIKMNPR
    21stUESTCProgrammingContest-PreliminaryexceptBCGIKMNPR OK,那么长的except那我到底写了什么呢(悲,太菜啦) A.能量采集dp+组合数的应用用dp[i][j][p]表示在(i,j)这个点以连续个p结尾的路径数1.首先对于每一个A到达这个格子的方案数是{n-i+m-j\choosen-i}......
  • AtCoder 好题选做
    AtCoderRegularContest091-F-StrangeNimhttps://atcoder.jp/contests/arc091/tasks/arc091_d清北学堂讲的一道题,我艹感觉这结论很难猜啊。做这种题一定是先写爆搜打表啊,先写了一个博弈论求SG函数:然后发现了一个规律:\(\text{SG}(nk,k)=n\)。还有一个规律:当\(n<k......
  • AtCoder Beginner Contest 298 题解
    题面:https://atcoder.jp/contests/abc298/tasks_printA-JobInterview直接模拟即可。#include<bits/stdc++.h>#include<ext/pb_ds/assoc_container.hpp>#include<ext/pb_ds/tree_policy.hpp>#include<ext/pb_ds/hash_policy.hpp>usingnamespace......
  • AtCoder DP系列刷题记录
    直面自己的弱点。AFrog1简单线性\(\text{dp}\),令\(dp_i\)为跳到第\(i\)块石头的最小花费,易得:\[dp_i+=\min(|a_i-a_{i-1}|,|a_i-a_{i-2}|)\]BFrog2很快就写完了,但是一直调了十分钟,耻辱啊。如果反着跳,第\(i\)根木桩只能从第\(i+1\)或\(i+2\)木桩上跳到,则有:\[d......
  • AtCoder Beginner Contest 234 Ex Enumerate Pairs
    洛谷传送门AtCoder传送门把每个点分到\((\left\lfloor\frac{x}{K}\right\rfloor,\left\lfloor\frac{y}{K}\right\rfloor)\)的正方形内,枚举相邻正方形,计入答案。正确性显然。复杂度证明就是所有每个正方形内距离为\(K\)的点对下界为\(\Omega(n^2)\)。考虑分成四个边长为......
  • AtCoder Beginner Contest 221 F Diameter set
    洛谷传送门AtCoder传送门显然,选出的每两个点都要组成一条直径。还是显然,每条直径的重合部分只可能是一个点或一条边。简单证一下,没有重合显然不可能,重合超过一个点或一条边,直径会更长。进一步发现,设直径点数为\(x\),如果\(x\nmid2\),重合部分是一个点,否则重合部分是一条边......
  • AtCoder Beginner Contest 206(Sponsored by Panasonic)(E,F)
    AtCoderBeginnerContest206(SponsoredbyPanasonic)(E,F)E(容斥,gcd)E这个题大意就是给出一个\(l\)和一个\(r\),寻找满足以下条件的一对数\((x,y)\)的数量\(gcd(x,y)!=1\)\(gcd!=x\)并且\(gcd!=y\)(从这一句我们可以知道\(x\)不可能被\(y\)整除)那么我们可以设\(x\)是\(t\)的倍......