首页 > 其他分享 >AtCoder Grand Contest 012 E Camel and Oases

AtCoder Grand Contest 012 E Camel and Oases

时间:2024-02-15 21:55:34浏览次数:42  
标签:AtCoder typedef Camel int Contest long maxn define

洛谷传送门

AtCoder 传送门

容易发现跳跃次数为 \(O(\log V)\)。考虑对于跳跃 \(k\) 次后的限制 \(\left\lfloor\frac{V}{2^k}\right\rfloor\),对每个点预处理出不再跳跃能到达的最左和最右的点 \([l_{k, i}, r_{k, i}]\)。

于是问题变成了,从第 \(i\) 个区间集选择一个区间 \([a_i, b_i]\),若这些区间的并集是 \([1, n]\),那么这种方案会使得 \([a_0, b_0]\) 能够到达全部点。

\([a_0, b_0]\) 看起来比较烦。先把第 \(0\) 个区间集扔掉。设当前的区间集的集合为 \(U\),\(f_S\) 为从 \(S\) 中的每个区间集选出一个区间能覆盖的最大前缀右端点,同时设 \(g_S\) 为能覆盖的最大后缀的左端点。\(f_S, g_S\) 可以状压 dp 求出。枚举覆盖了一段前缀的集合 \(S\),设 \(T = U \setminus S\),那么 \(T\) 覆盖了一段后缀。

若 \(f_S + 1 \ge g_T\),那么 \(U\) 满足从每个区间集选出一个区间能覆盖 \([1, n]\),此时就是全部 Possible;否则 \([f_S + 1, g_T - 1] \subseteq [a_0, b_0] = [l_{0, f_S + 1}, r_{0, f_S + 1}]\)。若 \(r_{0, f_S + 1} + 1 \ge g_T\) 那么 \([l_{0, f_S + 1}, r_{0, f_S + 1}]\) 就能到达全部点。

时间复杂度 \(O((n + V) \log V)\)。

code
// Problem: E - Camel and Oases
// Contest: AtCoder - AtCoder Grand Contest 012
// URL: https://atcoder.jp/contests/agc012/tasks/agc012_e
// Memory Limit: 256 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 mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

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

const int maxn = 200100;

ll n, m, a[maxn], K = -1, b[99], d[maxn], f[maxn * 5], g[maxn * 5];
pii c[20][maxn];

void solve() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
	}
	ll x = m;
	while (x) {
		b[++K] = x;
		x >>= 1;
	}
	b[++K] = 0;
	reverse(b, b + K + 1);
	for (int k = 0; k <= K; ++k) {
		for (int i = 1, j = 1; i <= n; i = (++j)) {
			while (j < n && a[j + 1] - a[j] <= b[k]) {
				++j;
			}
			for (int l = i; l <= j; ++l) {
				c[k][l] = mkp(i, j);
			}
		}
	}
	for (int S = 0; S < (1 << K); ++S) {
		f[S] = 0;
		g[S] = n + 1;
	}
	for (int S = 0; S < (1 << K); ++S) {
		for (int i = 0; i < K; ++i) {
			if (S & (1 << i)) {
				continue;
			}
			f[S | (1 << i)] = max(f[S | (1 << i)], c[i][f[S] + 1].scd);
			g[S | (1 << i)] = min(g[S | (1 << i)], c[i][g[S] - 1].fst);
		}
	}
	for (int S = 0; S < (1 << K); ++S) {
		int T = (1 << K) - 1 - S;
		if (f[S] + 1 >= g[T]) {
			for (int i = 1; i <= n; ++i) {
				puts("Possible");
			}
			return;
		}
		pii p = c[K][f[S] + 1];
		if (p.scd + 1 >= g[T]) {
			++d[p.fst];
			--d[p.scd + 1];
		}
	}
	for (int i = 1; i <= n; ++i) {
		d[i] += d[i - 1];
		puts(d[i] ? "Possible" : "Impossible");
	}
}

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

标签:AtCoder,typedef,Camel,int,Contest,long,maxn,define
From: https://www.cnblogs.com/zltzlt-blog/p/18016656

相关文章

  • AtCoder Beginner Contest 340 题解
    AtCoderBeginnerContest340题解去我的洛谷博客里看这篇文章!A-ArithmeticProgression模拟即可。//2024/2/11PikachuQAQ#include<iostream>usingnamespacestd;inta,b,d;intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>......
  • AtCoder Beginner Contest 340 题解
    AtCoderBeginnerContest340题解去我的洛谷博客里看这篇文章!A-ArithmeticProgression模拟即可。//2024/2/11PikachuQAQ#include<iostream>usingnamespacestd;inta,b,d;intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>......
  • KAJIMA CORPORATION CONTEST 2024(AtCoder Beginner Contest 340)
    KAJIMACORPORATIONCONTEST2024(AtCoderBeginnerContest340)A-ArithmeticProgression代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128......
  • Atcoder ABC340(A-D)
    A题题意:给出一个首项为A,尾项为B,公差为D的算数序列,要求输出符合条件的序列思路:只需要从首项开始每次加上公差输出即可代码:#include<bits/stdc++.h>#defineiosios::sync_with_stdio(false);cin.tie(0);cout.tie(0)usingnamespacestd;intadd(intx,inty){returnx......
  • AtCoder Beginner Contest 340 考试总结
    前言可惜的是我是VP的,却打得相对较好(服了。得分明细:ABCDEFGTotal√√√√√√×2625改题明细:ABCDEFG√√√√√√×第一次打AT,发挥还可以。A.ArithmeticProgressionProblem打印一个包含第一项\(A\),最后一项\(B\)......
  • Atcoder Educational DP Contest 题解
    比赛链接:Atcoderr或者题单A:Frog1常规线性dp,注意到对于每个落点来说,青蛙只能由第\(i-1\)个石头或者第\(i-2\)个石头转移得到,那么我们让\(dp[i]\)为当跳到第\(i\)个石头上的最小费用。此时显然有:\[dp_i=\min(dp_{i-1}+\left|h_i-h_{i-1}\right|,dp_{i-2}+\left|h_......
  • AtCoder-abc340_f题解
    题意简述给定整数\(x,y\),询问是否存在整数\(a,b\),满足:\(-10^{18}\lea,b\le10^{18}\)。由\((0,0),(x,y),(a,b)\)三点构成的三角形面积为\(1\)。如果存在,输出任意一组;否则输出-1。思路先假设\(x,y,a,b\)都是正数。那么图大概是这样:此时红色三角形的面积就......
  • AtCoder Beginner Contest 340
    A-ArithmeticProgression(abc340A)题目大意给定等差数列的首项、末项、公差。输出这个等差数列。解题思路从首相依次累加公差到末项即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_std......
  • The 18th Heilongjiang Provincial Collegiate Programming Contest
    A.MagicComputer看题目猜规律#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongusingvi=vector<int>;usingi32=int32_t;constintmod=998244353;intpower(intx,inty){intans=1;while(y){if(y&......
  • Atcoder Grand Contest 056 B - Range Argmax
    因为一组\(x\)可能对应多组\(p\),考虑怎么让决策唯一化。我们从大到小依次钦定每个值的位置,即倒着遍历\(i=n,n-1,\cdots,1\),找到最左端的位置\(v\)满足,对于现在还活着的所有区间\(j\)满足\(l_j\lev\ler_j\),都有\(x_j=v\),令\(p_j=i\),然后删去所有包含\(i\)的区间。......