Codeforce 1236 E. Alice and the Unfair Game(思维,dp,并查集)

8 篇文章 0 订阅

题目大意:初始有 n 个盒子 和 一个小球,A 和 B 玩一个游戏。游戏过程如下:
A将小球放在某一个盒子内,然后 B 来猜小球在哪个盒子,每一次B会询问小球是否在 他猜的数字 a i a_i ai 中。游戏共进行 m 轮,A为了不让B赢,在每一次 B 猜的时候 A可以移动小球到相邻位置,游戏开始前和游戏结束后 A 也可以移动小球一次。

设A初始将球放在 x x x 位置,游戏结束后球最后的位置在 y y y,问有多少种点对 ( x , y ) (x,y) (x,y) 是可能的结果。


一个结论是,对于每一个起点,能到达的终点是一段连续的区间。因为小球可以移动也可以等待,假设小球到达的位置是不连续的区间,那么小球总能先到达两边的位置然后等待最后移动到被 ban 的位置。

那么一个做法是,对于每一个位置,只需要找出它能走到的最左边和最右边就能得到答案。

将问题转化为一个 m ∗ n m * n mn 的方格图模型,在 ( i , a i ) (i,a_i) (i,ai)上有一个障碍物,初始你在 ( 0 , y ) (0,y) (0,y) 位置,每一次可以向左下,下,右下三个方向移动,不能碰到障碍物,求能走到的最多端和最右端,

考虑只处理能走到的最左端。对于每一个起点,贪心的做法是不停的往左下走,遇到障碍物就向下走。对于每一个障碍物,只会影响到一个点的答案,这个点不得不向下走一次,而向下走一次等价于起点向右移动一次。

用一个数组记录每一个起点向左走的过程中必须向下走几次,将障碍物倒着放,然后递推,求右边界是类似的方法。


代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
typedef long long ll;
int L[maxn],R[maxn];
int a[maxn],n,m;
const int p = 1e5;
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; i++)
		scanf("%d",&a[i]);
	for(int i = m; i >= 1; i--) {
		L[a[i] + i + p] = L[a[i] + i + 1 + p] + 1;
		R[a[i] - i + p] = R[a[i] - i - 1 + p] + 1; 
	}
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		int l = max(1,i - m - 1 + L[i + p]);
		int r = min(n,i + m + 1 - R[i + p]);
		ans += r - l + 1;
	}
	if(n == 1) ans = 0;
	printf("%lld\n",ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值