首页 > 其他分享 >AtCoder Regular Contest 125 F Tree Degree Subset Sum

AtCoder Regular Contest 125 F Tree Degree Subset Sum

时间:2023-05-03 15:12:37浏览次数:41  
标签:Subset AtCoder typedef Degree Contest int long maxn

洛谷传送门

AtCoder 传送门

首先将度数 \(-1\)。

设 \(f_i\) 为体积为 \(i\) 至多能用几个物品凑出来,\(g_i\) 为至少。

我们现在要证明一个东西:\(x \in [g_i, f_i]\),\((i, x)\) 合法。

首先若 \((s, x)\) 合法,那么必须满足 \(s - x \in [-z, z - 2]\),其中 \(z = \sum\limits_{i=1}^n [d_i = 0]\)。

因为 \(s - x = \sum\limits_{y \in S} (y - 1)\),最小值就是把 \(< 1\) 的值加起来,最大值就是把 \(\ge 1\) 的值加起来。

然后 \([g_i, g_i + z]\) 一定能通过最少的方案后面加若干 \(0\) 凑出来,\([f_i - z, f_i]\) 同理。

那么只要满足 \(g_i + z + 1 \ge f_i - z\) 即 \(f_i - g_i \le 2z + 1\) 即可。

\((i, f_i)\) 和 \((i, g_i)\) 合法,那么 \(i - f_i \in [-z, z - 2], i - g_i \in [-z, z - 2]\),所以它们的差 \(\in [0, 2z - 2]\),得证。

和为 \(n\) 的数中至多有 \(O(\sqrt{n})\) 种不同的数。枚举这 \(n\) 个数,做多重背包即可。肯定不能直接朴素做,容易按照同余系分开考虑,单调队列优化。

code
// Problem: F - Tree Degree Subset Sum
// Contest: AtCoder - AtCoder Regular Contest 125
// URL: https://atcoder.jp/contests/arc125/tasks/arc125_f
// Memory Limit: 1024 MB
// Time Limit: 6000 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 long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

int n, a[maxn], f[maxn], g[maxn], h[maxn], q[maxn], b[maxn];

void solve() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		++a[u];
		++a[v];
	}
	mems(f, -0x3f);
	mems(g, 0x3f);
	for (int i = 1; i <= n; ++i) {
		--a[i];
		++b[a[i]];
	}
	f[0] = g[0] = 0;
	for (int i = 1; i <= n; ++i) {
		if (!b[i]) {
			continue;
		}
		for (int j = 0; j <= n; ++j) {
			h[j] = f[j];
		}
		for (int j = 0; j < i; ++j) {
			int hd = 1, tl = 0;
			for (int k = j; k <= n; k += i) {
				while (hd <= tl && q[hd] < k - i * b[i]) {
					++hd;
				}
				if (hd <= tl) {
					f[k] = max(f[k], h[q[hd]] + (k - q[hd]) / i);
				}
				while (hd <= tl && h[q[tl]] - q[tl] / i <= h[k] - k / i) {
					--tl;
				}
				q[++tl] = k;
			}
		}
	}
	for (int i = 1; i <= n; ++i) {
		if (!b[i]) {
			continue;
		}
		for (int j = 0; j <= n; ++j) {
			h[j] = g[j];
		}
		for (int j = 0; j < i; ++j) {
			int hd = 1, tl = 0;
			for (int k = j; k <= n; k += i) {
				while (hd <= tl && q[hd] < k - i * b[i]) {
					++hd;
				}
				if (hd <= tl) {
					g[k] = min(g[k], h[q[hd]] + (k - q[hd]) / i);
				}
				while (hd <= tl && h[q[tl]] - q[tl] / i >= h[k] - k / i) {
					--tl;
				}
				q[++tl] = k;
			}
		}
	}
	ll ans = 0;
	for (int i = 0; i <= n; ++i) {
		if (f[i] >= 0) {
			ans += f[i] - g[i] + 1 + b[0];
		}
	}
	printf("%lld\n", ans);
}

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

标签:Subset,AtCoder,typedef,Degree,Contest,int,long,maxn
From: https://www.cnblogs.com/zltzlt-blog/p/17369082.html

相关文章

  • AT_abc106_d [ABC106D] AtCoder Express 2 题解
    题目传送门解题思路区间\(dp\)。划分阶段:以左右城市之间的列车数量为阶段。状态表达:设\(f_{i,j}\)为城市\(i\)与城市\(j\)之间的列车数量。状态转移:由图可知,城市\(l\)与城市\(r\)之间的列车数量,就是城市\(l\)与城市\(r-1\)之间的列车数量与城市\(l+1\)与......
  • AtCoder Regular Contest 119 F AtCoder Express 3
    洛谷传送门AtCoder传送门很厉害的题!考虑所有车站已确定,如何求\(0\)到\(n+1\)的最短路。设\(g_{i,0}\)为只考虑\(0\simi\)的点,到\(i\)和它左边第一个\(\text{A}\)的最短路,\(g_{i,1}\)同理。有转移:若\(s_{i-1}=\text{A},s_i=\text{A},g_{i,0}\getsg_{......
  • AtCoder Regular Contest 119 D Grid Repainting 3
    洛谷传送门AtCoder传送门对每个红格的行和列连边,建出二分图。对于二分图中的每个连通块分别考虑。大胆猜测对于每个连通块,我们都能够进行适当的操作,使得只有一行/一列没被操作(显然不能使所有行和列都被操作)。对应的方案就是随便取一棵生成树,把不被染白的那一行/列拎出来当根,然......
  • AtCoder Regular Contest 117 F Gateau
    洛谷传送门AtCoder传送门差分约束算法:给出\(m\)个不等式形如\(x_{a_i}\lex_{b_i}+y_i\),求是否有解。考虑把不等式看成图上的三角不等式\(dis_v\ledis_u+d\),连边\((b_i,a_i,y_i)\),以\(x_i\)最大的位置跑最短路,如果图中有负环就无解。此时求出来的\(dis_i\)......
  • Atcoder Grand Contest 059 E - Grid 3-coloring(转化+思维)
    首先先是一步很猛的操作——将三染色视作构造一个矩阵使得相邻元素相差\(1\)且每个元素\(\bmod3\)的值就等于其颜色。证明是显然的,我们按从上到下从左到右的顺序填数,可以归纳证明,对于一个相邻格子颜色互不相同的矩阵的填数方案,处于斜对角的两个格子上写的数要么差\(2\),要么......
  • AtCoder Regular Contest 122 D XOR Game
    洛谷传送门AtCoder传送门从高到低按位考虑。设当前位有\(k\)个\(1\)。如果\(k\bmod2=0\),这意味着Alice如果选了一个数,Bob可以选相同的数。发现可以分成\((0,0),(1,1)\)两组,递归下去即可。如果\(k\bmod2=1\),意味着答案这一位一定是\(1\)(因为无论如何都不......
  • AtCoder Regular Contest 119 E Pancakes
    洛谷传送门AtCoder传送门感觉挺典的,为啥有2500啊(观察发现,反转序列对\(\sum\limits_{i=1}^{n-1}|a'_i-a'_{i+1}|\)影响不大。具体而言,设反转了\(a_l\sima_r\),记\(s=\sum\limits_{i=1}^{n-1}|a_i-a_{i+1}|\),那么\(s'=s-|a_{l-1}-a_l|-|a_r-a_{r+1}|......
  • AtCoder Regular Contest 117 D Miracle Tree
    洛谷传送门AtCoder传送门第一步就没想到可以考虑化简限制。设所有点按\(E_i\)从小到大排序后顺序是\(p_1,p_2,...,p_n\)。发现只需满足\(E_{p_{i+1}}-E_{p_i}\ge\operatorname{dis}(p_i,p_{i+1})\)。证明是对于任意\(i<j<k\),若\(p_i,p_j\)和\(p_j,p_k\)均满......
  • AtCoder Beginner Contest 231
    A-WaterPressure#include<bits/stdc++.h>usingnamespacestd;intmain(){ intn; cin>>n; printf("%.6lf\n",n/100.0);return0;}B-Election#include<bits/stdc++.h>usingnamespacestd;intmain(){ ios:......
  • AtCoder比赛记录(一)
    这里记录的是这个账号的比赛情况。ARC1572023-2-25Solved:4/62189->2216C(Medium,1802)给定一个XY矩阵,一条左上角到右下角的路径的分值定义为路径上连续两个Y的组数。求所有可能路径的分值的平方和。Solution:经典DP。递推两个量,一个是到(i,j)所有路径的分值和\(f_{i,j}\),......