Codeforces Round #593 (Div. 2) D. Alice and the Doll 暴力 + 二分

传送门

文章目录

题意:

在这里插入图片描述

思路:

还以为这个题有什么高深的算法,结果就是个暴力。
由于 n ∗ m n*m nm达到了 1 e 10 1e10 1e10的级别,所以直接暴力肯定是不行的,考虑有很多空格,我们可以维护四个变量表示边界,让后在当前轴上二分最近的障碍点,让后判断即可。
实现的时候可以加两个边界比较方便。
要注意如果枚举的四个方向,如果有一个方向不能走的话不能直接退出,有如下样例:
3    3 3\ \ 3 3  3
0    1    1 0\ \ 1\ \ 1 0  1  1
0    1    1 0\ \ 1\ \ 1 0  1  1
0    1    1 0\ \ 1\ \ 1 0  1  1
1 1 1代表障碍,一开始是向右走,显然不能走,如果直接退出就错了,我们还可以向下走。
只有这一种情况,所以特判一下是不是起点即可。

还有注意二分前先给数组排个序。。。
没排序卡了我半天。

// Problem: D. Alice and the Doll
// Contest: Codeforces - Codeforces Round #593 (Div. 2)
// URL: https://codeforces.com/contest/1236/problem/D
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n,m,k;
vector<int>x[N],y[N];

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
	
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++) x[i].pb(0);
	for(int i=1;i<=m;i++) y[i].pb(0);
	for(int i=1;i<=k;i++) {
		int xx,b; scanf("%d%d",&xx,&b);
		x[xx].pb(b); y[b].pb(xx);
	}
	for(int i=1;i<=n;i++) sort(x[i].begin(),x[i].end()),x[i].pb(m+1);
	for(int i=1;i<=m;i++) sort(y[i].begin(),y[i].end()),y[i].pb(n+1);
	int sx,ex,sy,ey;
	sx=sy=0; ex=n+1; ey=m+1;
	LL sum=0;
	int dx,dy; dx=dy=1;
	int op=0;
	while(1) {
		if(op%4==0) {
			int pos=lower_bound(x[dx].begin(),x[dx].end(),dy)-x[dx].begin();
			int add=min(x[dx][pos],ey);
			if(add-1<=dy) {
				if(op==0) {
					sum++; op++;
					continue;
				} else break;
			} 
			sum+=add-dy;
			dy=add-1; 
			ey=dy; sx=dx;
		} else if(op%4==1) {
			int pos=lower_bound(y[dy].begin(),y[dy].end(),dx)-y[dy].begin();
			int add=min(y[dy][pos],ex);
			if(add-1<=dx) break;
			sum+=add-dx;
			dx=add-1; 
			ex=dx; ey=dy;
		} else if(op%4==2) {
			int pos=upper_bound(x[dx].begin(),x[dx].end(),dy)-x[dx].begin();
			pos--;
			int add=max(x[dx][pos],sy);
			if(add+1>=dy) break;
			sum+=dy-add;
			dy=add+1; 
			sy=dy; ex=dx;
		} else if(op%4==3) {
			int pos=upper_bound(y[dy].begin(),y[dy].end(),dx)-y[dy].begin();
			pos--;
			int add=max(y[dy][pos],sx);
			if(add+1>=dx) break;
			sum+=dx-add;
			dx=add+1; 
			sx=dx; sy=dy;
		}
		op++; 
	}
	sum-=op-1;
	if(sum==1ll*n*m-k) puts("Yes");
	else puts("No");
	
	



	return 0;
}
/*


*/









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值