CF1733E Conveyor 题解

CF1733E Conveyor

题意:

有个 120 120 120 行, 120 120 120 列的棋盘。每个格子初始方向向右。每秒 ( 0 , 0 ) (0,0) (0,0) 产生一个史莱姆,所有史莱姆随格子方向移动。接着所有格子改变方向,向右变为向下,向下变成向右。若两个史莱姆相遇则合并为一个。 q q q 次询问,第 t t t 秒时 ( x , y ) (x,y) (x,y) 是否有。
t ≤ 1 0 18 t\leq 10^{18} t1018

思路:

注意每一秒是每个格子都会变方向的。
这里的 t t t 很大,直接求不现实。我们把求是否有转化为求差分是否为正。
每个格子经过的史莱姆一定是一半向下,一半向右的,这样就好转移了。 f i , j f_{i,j} fi,j 表示第 i i i j j j 列通过的史莱姆数量。从 f i , j f_{i,j} fi,j 转移到 f i + 1 , j f_{i+1,j} fi+1,j f i , j + 1 f_{i,j+1} fi,j+1。暴力算 f x , y f_{x,y} fx,y 分别在 f 0 , 0 f_{0,0} f0,0 t t t t + 1 t+1 t+1 时的答案,时间复杂度 O ( q x y ) O(qxy) O(qxy)

code:

#include
using namespace std;
const int N=122;
#define ll long long
int q;
ll x,y;
ll t; 
ll f1[N][N],f2[N][N];
int main(){
	scanf("%d",&q);
	while(q--){
		scanf("%lld%lld%lld",&t,&x,&y);
		memset(f1,0,sizeof f1);
		memset(f2,0,sizeof f2);
		f1[0][0]=t-x-y;
		f2[0][0]=t-x-y+1;
		for(int i=0;i<=x;i++){
			for(int j=0;j<=y;j++){
				if(i){
					f1[i][j]=f1[i-1][j]/2;
					f2[i][j]=f2[i-1][j]/2;
				}
				if(j){
					f1[i][j]+=(f1[i][j-1]+1)/2;
					f2[i][j]+=(f2[i][j-1]+1)/2;
				}
			}
		} 
		if(f2[x][y]>f1[x][y]) printf("YES\n");
		else printf("NO\n"); 
		
	} 
	return 0;
} 

思考:

直接算不好算时考虑差分。

你可能感兴趣的:(CF1733E Conveyor 题解)