首页 > 其他分享 >CF1809F Traveling in Berland - 倍增 -

CF1809F Traveling in Berland - 倍增 -

时间:2023-03-25 17:48:01浏览次数:34  
标签:cnt dist Berland int sum CF1809F cost maxn Traveling

题目链接:https://codeforces.com/contest/1809/problem/F

题解:
对一个点,考虑怎样在 \(O(\log n)\) 的时间复杂度内求出答案,联想到倍增
但是,倍增合并的时候只能在两个状态相同的情况下合并,但是如果我们直接从 \(i\) 到 \(i+1\) 这样算的话,每次剩余的油量是不同的,很难合并。
考虑如果将每次剩余油量都设为 0 的话,就比较容易合并了。
如果当前位置 \(b_i=2\),那么直接付清 \(2\times a_i\) 的钱,然后移动到下一个
如果当前位置 \(b_i=1\),且往后第一个不是 \(2\),那么付清 \(a_i\) 的钱,然后移动到下一个
否则,比如说有 \(k\) 个连续的 \(2\),考虑二分出第一个 \(sum[l..r] \geq k\) 的 \(r\),显然在 \(b_i\) 处先加满油最优,那么到了 \(r\) 处可能刚好够用,也可能需要再买一些。如果需要再买一些的话,显然就是 \(2\times (sum[l..r]-k)\) 的额外价格。
这样一来,我们就求得了 \(dist[i][0]\) 代表 \(i\) 往后移动 \(2^0\) 次的距离,已经此时的价格,倍增即可

对于每个 \(i\),查询的时候就倍增往后跳,注意可能出现没跳完的情况,即某一次 \(i\) 即使是 \(dist[i][0]\) 也 < 剩余的距离(这是有可能的,因为我们每次 \(dist\) 都是取的最大值),容易发现此时当前位置一定为 \(b_i=1\),直接求出二者的距离,在 \(b_i=1\) 处买即可

细节很多,调吐了

// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back

using namespace std;

typedef long long ll;
typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 4e5+5;

int n,k;
int a[maxn], b[maxn];
ll dist[maxn][20], cost[maxn][20], sum[maxn];

int md(int x){
	if(x <= n)return x;
	return x-n;
}

void solve(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]), a[i+n] = a[i];
	for(int i=1;i<=n;i++)scanf("%d",&b[i]), b[i+n] = b[i];
	
	sum[0] = 0;
	for(int i=1;i<=2*n;i++)sum[i] = sum[i-1] + a[md(i)];
	
	int cnt = 0;
	
	for(int i=2*n;i>=1;i--){
		if(b[i] == 2){
			cost[i][0] = 2*a[i];
			dist[i][0] = 1;
		}else if(cnt == 0){
			cost[i][0] = a[i];
			dist[i][0] = 1;
		}else{
			int to = lower_bound(sum+i, sum+i+cnt+1, sum[i-1] + k) - sum;
			if(to == i+cnt+1){
				cost[i][0] = sum[i+cnt] - sum[i-1];
				dist[i][0] = cnt+1;
			}else{
				int delt = to - i;
				if(sum[to] == sum[i-1] + k){
					cost[i][0] = k;
					dist[i][0] = delt+1;
				}else{
					cost[i][0] = k + 2 * (sum[to] - sum[i-1] - k);
					dist[i][0] = delt+1;
				}
			}
		}
		if(b[i] == 2)++ cnt;
		else cnt = 0;
	}
	
	for(int j=1;j<=18;j++)
		for(int i=1;i<=n;i++){
			dist[i][j] = dist[i][j-1] + dist[md(i + dist[i][j-1])][j-1];
			cost[i][j] = cost[i][j-1] + cost[md(i + dist[i][j-1])][j-1];
		}
	
	for(int i=1;i<=n;i++){
		ll r = 0, now = i;
		int tot = 0;
		for(int j=18;j>=0;j--){
			if(tot+dist[now][j] <= n)
				r += cost[now][j],
				tot += dist[now][j],
				now = md(now + dist[now][j]);
		}
		if(tot < n){
			r += sum[i+n-1] - sum[i+tot-1];
		}
		printf("%lld ",r);
	}
	puts("");
}

signed main(){
	int te;scanf("%d",&te);
	while(te --)solve();

	return 0;
}

标签:cnt,dist,Berland,int,sum,CF1809F,cost,maxn,Traveling
From: https://www.cnblogs.com/SkyRainWind/p/17255212.html

相关文章

  • CF-25C - Roads in Berland(水题)
    C-RoadsinBerlandCrawlinginprocess...CrawlingfailedTimeLimit:2000MSMemoryLimit:262144KB64bitIOFormat:%I64d&%I64u​​Submit​​​......
  • CF-25D - Roads not only in Berland(并查集或者搜索)
    D-RoadsnotonlyinBerlandCrawlinginprocess...CrawlingfailedTimeLimit:2000MSMemoryLimit:262144KB64bitIOFormat:%I64d&%I64u​​Submit​​......
  • CF846E - Chemistry in Berland
    题意:有一颗树,每个点上有\(b_i\)东西,从叶子往上的汇率是\(1:1\),从父亲往下的汇率是\(k:1\),求能否使每个点的东西都不少于\(a_i\)。我们发现,从上往下肯定是不划算的,我......
  • CF808G Anthem of Berland 解题报告
    Description给定$s$串和$t$串,其中$s$串包含小写字母和问号,$t$串只包含小写字母。假设共有$k$个问号。你需要给把每个问号变成一个小写字母,共有$26^k$种可能......
  • CF808G Anthem of Berland
    \(\mathcalLink\)大概知道两种DP方法。(\(n\logn\)做法太神了)方法一:设\(f_i\)表示\(t\)在\(s[1\cdotsi]\)最多出现次数。当最后一位不会被匹配时,答案为\(f_......
  • Codeforces 1 C. Ancient Berland Circus
    题意:二维平面中,给定三个点,这三个点是正多边形的三个顶点,求正多边形最小的面积。思路:两对点分别求中垂线,相交点是多边形外接圆的圆心,圆心有了半径和角度也就有了,之后求一......
  • CF546E Soldier and Traveling
    CF546ESoldierandTraveling英文原题:当然Luogu有中文翻译对于这种类型的题目,又是增加,又是减少的,我们可以使用网络流进行转化。说句废话:网络流这个东西,趣味十足,上......
  • HOJ Recoup Traveling Expenses(最长递减子序列变形)
    Apersonwantstotravelaroundsomeplaces.Thewelfareinhiscompanycancoversomeoftheairfarecost.Inordertocontrolcost,thecompanyrequiresthat......
  • CF1C Ancient Berland Circus
    给定\(3\)个点,求以这\(3\)个点为顶点的正多边形面积最小值。先以这张图为例,首先可以肯定圆的半径是确定的。根据秦九韶公式,有\(S_{\triangleABC}=\sqrt{p(p-a)(p......
  • CF808G Anthem of Berland
    给定\(s\)和\(t\),其中\(s\)中有\(k\)个?,求\(s\)补齐?后匹配\(t\)的最大次数。\(|s|\times|t|\leq10^7\)。先用一组数据\(HACK\)掉贪心做法:(贪心只......