首页 > 其他分享 >AtCoder Regular Contest 117 F Gateau

AtCoder Regular Contest 117 F Gateau

时间:2023-05-02 10:56:29浏览次数:50  
标签:AtCoder int ll add edges edge 117 Regular mems

洛谷传送门

AtCoder 传送门

差分约束算法:给出 \(m\) 个不等式形如 \(x_{a_i} \le x_{b_i} + y_i\),求是否有解。
考虑把不等式看成图上的三角不等式 \(dis_v \le dis_u + d\),连边 \((b_i, a_i, y_i)\),以 \(x_i\) 最大的位置跑最短路,如果图中有负环就无解。此时求出来的 \(dis_i\) 是 \(x_i \le 0\) 的最大解。

考虑二分答案 \(x\),记 \(s\) 为前缀和数组,那么我们可以得到不等式:

  • \(s_0 = 0, s_{2n} = x\),连边 \((0, 2n, x), (2n, 0, -x)\);
  • \(s_i - s_{i-1} \ge 0\),连边 \((i, i - 1, 0)\);
  • \(i \in [0,n), s_{i+n} - s_i \ge a_i\),连边 \((i + n, i, -a_i)\);
  • \(i \in [0,n), x - (s_{i+n} - s_i) \ge a_{i+n}\),连边 \((i, i + n, x - a_{i+n})\)。

直接跑 spfa 会 T。注意到删去 \(n\) 点后图长这样:

可以 dp 求出 \(2n\) 到 \(n-1, n+1, 0\) 的最短路,以及 \(n-1\) 到 \(0, n+1\) 的最短路。加上新点 \(n\) 后,只用计算与新加边有关的点,把整张图缩成 \(0, n-1, n, n+1, 2n\) 五个点,在新图上跑 spfa 即可。

总结:这种差分约束但是又不能直接跑 spfa 的题,考虑观察图的形态,用 dp 求出最短路,或者缩点。

code
// Problem: F - Gateau
// Contest: AtCoder - AtCoder Regular Contest 117
// URL: https://atcoder.jp/contests/arc117/tasks/arc117_f
// Memory Limit: 1024 MB
// Time Limit: 3000 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 = 300100;
const ll inf = 0x3f3f3f3f3f3f3f3fLL;

ll n, a[maxn], m, f[maxn], head[maxn], len, g[maxn];
bool vis[maxn];

struct edge {
	ll to, dis, next;
} edges[99];

inline void add_edge(ll u, ll v, ll d) {
	edges[++len].to = v;
	edges[len].dis = d;
	edges[len].next = head[u];
	head[u] = len;
}

inline bool spfa() {
	queue<int> q;
	mems(f, 0x3f);
	mems(vis, 0);
	mems(g, 0);
	f[m] = 0;
	g[m] = 1;
	vis[m] = 1;
	q.push(m);
	while (q.size()) {
		int u = q.front();
		q.pop();
		vis[u] = 0;
		for (int i = head[u]; i; i = edges[i].next) {
			ll v = edges[i].to, d = edges[i].dis;
			if (f[v] > f[u] + d) {
				f[v] = f[u] + d;
				if (!vis[v]) {
					vis[v] = 1;
					if ((++g[v]) >= 8) {
						return 0;
					}
					q.push(v);
				}
			}
		}
	}
	return 1;
}

inline bool check(ll x) {
	len = 0;
	mems(head, 0);
	mems(f, 0);
	f[m - 1] = f[m] = 0;
	f[n - 1] = -a[n - 1];
	for (int i = n - 2; i; --i) {
		f[i] = f[i + 1];
		f[i + n] = f[i + n + 1];
		ll p = f[i], q = f[i + n];
		f[i] = min(f[i], q - a[i]);
		f[i + n] = min(f[i + n], p + x - a[i + n]);
	}
	f[0] = f[1];
	add_edge(m, 0, f[0]);
	add_edge(m, n + 1, f[n + 1]);
	add_edge(m, n - 1, f[n - 1]);
	mems(f, 0);
	f[n - 1] = 0;
	f[m - 1] = x - a[m - 1];
	for (int i = n - 2; i; --i) {
		f[i] = f[i + 1];
		f[i + n] = f[i + n + 1];
		ll p = f[i], q = f[i + n];
		f[i] = min(f[i], q - a[i]);
		f[i + n] = min(f[i + n], p + x - a[i + n]);
	}
	f[0] = f[1];
	add_edge(n - 1, n + 1, f[n + 1]);
	add_edge(n - 1, 0, f[0]);
	add_edge(n, n - 1, 0);
	add_edge(n + 1, n, 0);
	add_edge(n, 0, -a[0]);
	add_edge(m, n, -a[n]);
	add_edge(0, m, x);
	add_edge(m, 0, -x);
	return spfa();
}

void solve() {
	scanf("%lld", &n);
	m = (n << 1);
	ll l = 0, r = 1e10, ans = -1;
	for (int i = 0; i < m; ++i) {
		scanf("%lld", &a[i]);
	}
	if (n == 1) {
		printf("%lld\n", a[0] + a[1]);
		return;
	}
	for (int i = 0; i < n; ++i) {
		l = max(l, a[i] + a[i + n]);
	}
	while (l <= r) {
		ll mid = (l + r) >> 1;
		if (check(mid)) {
			ans = mid;
			r = mid - 1;
		} else {
			l = mid + 1;
		}
	}
	printf("%lld\n", ans);
}

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

标签:AtCoder,int,ll,add,edges,edge,117,Regular,mems
From: https://www.cnblogs.com/zltzlt-blog/p/17367419.html

相关文章

  • Atcoder Grand Contest 059 E - Grid 3-coloring(转化+思维)
    首先先是一步很猛的操作——将三染色视作构造一个矩阵使得相邻元素相差\(1\)且每个元素\(\bmod3\)的值就等于其颜色。证明是显然的,我们按从上到下从左到右的顺序填数,可以归纳证明,对于一个相邻格子颜色互不相同的矩阵的填数方案,处于斜对角的两个格子上写的数要么差\(2\),要么......
  • Mastering Regular Expressions(精通正则表达式) 阅读笔记:第一章,概念
    RealScenario(现实场景)Here'sthescenario:you'regiventhejobofcheckingthepagesonawebserverfordoubledwords(suchas"thisthis"),acommonproblemwithdocumentssubjecttoheavyediting.任务:检查文本中重复的单词(doubledwords),比如&q......
  • 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}\),......
  • AtCoder比赛记录(二)
    这里记录的是这个账号的比赛情况。ABC3002023-4-29Solved:7/80->1200F(Medium-,1846)给定由o和x组成的字符串\(S\)。将\(S\)复制\(m\)遍,然后将其中\(k\)个x改成o,求改完之后连续的o最多可能有多少个。Solution:贪心。设最多能改完\(t\)个完整的\(S\),考虑三类情况:最长连续......
  • AtCoder Regular Contest 116 F Deque Game
    洛谷传送门AtCoder传送门很强的博弈+性质题。下文令A为Takahashi,B为Aoki。发现单独考虑一个序列\(a_1,a_2,...,a_n\):若\(n\bmod2=0\):若A为先手,答案为\(\max(a_{\frac{n}{2}},a_{\frac{n}{2}+1})\);若B为先手,答案为\(\min(a_{\frac{n}{2}},a_{\frac......
  • AtCoder Regular Contest 123 E Training
    洛谷传送门AtCoder传送门不妨假设\(B_X\leB_Y\)。设\(f(x)=A_X+\frac{x}{B_X},g(x)=A_Y+\frac{x}{B_Y},F(x)=\left\lfloor{f(x)}\right\rfloor,G(x)=\left\lfloor{g(x)}\right\rfloor\),题目即求\(\sum\limits_{x=1}^n[F(x)=G(x)]\)。我一开始尝试化简......