首页 > 其他分享 >题解:P11215 【MX-J8-T3】水星湖

题解:P11215 【MX-J8-T3】水星湖

时间:2024-10-23 13:47:27浏览次数:1  
标签:J8 int 题解 void T3 write vis inline define

依旧是模拟赛赛题。

Hint

Analysis

首先你注意到两棵相邻的树是一定不会死的,所以可能会死的只有自己种下去的树,队列维护。

接着考虑对于每个位置, \(\text{bfs}\) 维护一个最小的长出树的时间 \(vis[i][j]\),最后暴力统计答案即可。

具体细节看注释。

Code

#include<bits/stdc++.h>
#define pb push_back
#define is insert
#define fi first
#define se second
#define mkp make_pair
#define mathmod(a,m) (((a)%(m)+(m))%(m))
#define mem(a,b) memset(a,b,sizeof a)
#define cpy(a,b) memcpy(a,b,sizeof b)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace FastIO{
	const int MX=1<<20;
	#ifdef ONLINE_JUDGE
	char buf[MX],*p1,*p2;
	#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,MX,stdin),p1==p2)?0:*p1++)
	#else
	#define gc() getchar()
	#endif
	char pbuf[MX],*p3=pbuf;
	inline void pc(const char c){if(p3-pbuf==MX)fwrite(pbuf,1,MX,stdout),p3=pbuf;*p3++=c;}
	inline void flush(){fwrite(pbuf,1,p3-pbuf,stdout),p3=pbuf;}
	template<class T> inline void read(T& p){
		T x=0,f=1;char c=gc();
		while(c<'0'||c>'9'){if(c=='-')f=0;c=gc();}
		while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=gc();
		p=f?x:-x;
	}
	template<class T,class ... Args> inline void read(T& p,Args&... args){read(p),read(args...);}
	template<class T> inline void write(T x){
		if(!x){pc('0');return;}
		static short sta[40];short tp=0;
		if(x<0) pc('-'),x=-x;
		do{sta[tp++]=x%10,x/=10;}while(x);
		while(tp) pc(sta[--tp]+'0');
	}
	template< > inline void write(const char x){pc(x);}
	template< > inline void write(const char* x){for(int i=0;x[i];i++)pc(x[i]);}
	template< > inline void write(const string x){for(char c:x)pc(c);}
	template<class T,class ... Args> inline void write(T x,Args... args){write(x),write(args...);}
	#undef gc
}
using namespace FastIO;
const int N=3005;
const int INF=0x7f7f7f7f;
int n,m,q,r,k,tim,cnt,vis[N][N];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
short a[N][N];
struct Query{int t,x,y;};
queue<Query> que;
void bfs(Query s){
	queue<Query> q;
	// 开头也要判断,记得更新 vis
	if(vis[s.x][s.y]>s.t) vis[s.x][s.y]=s.t,q.push(s);
	while(!q.empty()){
		auto u=q.front();q.pop();
		for(int i=0;i<4;i++){
			int px=u.x+dir[i][0],py=u.y+dir[i][1],pt=u.t+1;
			if(px<1||px>n||py<1||py>m) continue;
			if(a[px][py]) continue; // 不是湖
			bool flag=0;
			for(int j=0;j<4;j++){ // 判断周围是否有水
				// 不能方向与 i 相反,可以看一下 dir[],小优化
				if(j==(i^1)) continue;
				int qx=px+dir[j][0],qy=py+dir[j][1];
				if(qx<1||qx>n||qy<1||qy>m) continue;
				if(a[qx][qy]){flag=1;break;}
			}
			if(!flag) continue;
			// 若不是更优的就没必要继续往下搜了,记得更新 vis
			if(vis[px][py]>pt) vis[px][py]=pt,q.push((Query){pt,px,py});
		}
	}
}
bool chk(int x,int y){
	for(int j=0;j<4;j++){
		int qx=x+dir[j][0],qy=y+dir[j][1];
		if(qx<1||qx>n||qy<1||qy>m) continue;
		if(a[qx][qy]||vis[qx][qy]<=tim) return true;
	}
	return false;
}
int main(){
	read(n,m,q,r,k);
	for(int i=1,ai1,bi1,ai2,bi2;i<=q;i++){
		read(ai1,bi1,ai2,bi2);
		for(int j=ai1;j<=ai2;j++) for(int k=bi1;k<=bi2;k++) a[j][k]=1;
	}
	mem(vis,0x7f);
	for(int i=1;i<=r;i++){
		Query tmp;read(tmp.t,tmp.x,tmp.y);
		tim=tmp.t;
		// 注意下面是 <tim,因为有可能有连续的相同的 t,所以等到他死透了再 pop 掉 :)
		while(!que.empty()&&que.front().t<tim){
			auto u=que.front();que.pop();
			if(!chk(u.x,u.y)) vis[u.x][u.y]=INF;
		}
		bfs(tmp);
		que.push((Query){tmp.t+k,tmp.x,tmp.y});
	}
	// t<=1e9,所以一个位置最晚在 1e9+3000*3000 个单位时间生长出树,暴力一点直接开到 2e9,注意 INF 也要开的比 2e9 大
	tim=2e9;
	while(!que.empty()&&que.front().t<tim){
		auto u=que.front();que.pop();
		if(!chk(u.x,u.y)) vis[u.x][u.y]=INF;
	}
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(!a[i][j]&&vis[i][j]<INF) cnt++;
	write(cnt,'\n'),flush();
	return 0;
}

好像还跑得挺快?最优解第二页?

标签:J8,int,题解,void,T3,write,vis,inline,define
From: https://www.cnblogs.com/godmoo/p/18496211

相关文章

  • CRC32爆破脚本 + [MoeCTF 2022]cccrrc 题解
    CRC32爆破原理介绍:CRC(循环冗余校验)是一种用于检测数据传输错误的技术。CRC算法生成一个校验值(校验和),这个值可以附加到数据后面,在数据接收方重新计算校验值并与附加的校验值进行比较,以此来确定数据是否在传输过程中发生了错误CRC32是一种常用的CRC算法,它的校验值长度固定为3......
  • P7910 [CSP-J 2021] 插入排序 题解
    正解首先要注意$2$点:修改数组元素的值会影响接下来的操作.对数组进行排序不会影响接下来的操作.思路直接扫一遍数组.假设排序后$a_x$会在第$p$位上.将$p$初始化为$n$.然后就开始找$x$前后有多少个小于$a_x$的值就行了.时间复杂度:$\Theta(nq)$.注意......
  • P7911 [CSP-J 2021] 网络连接 题解
    模拟代码#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;intn,p=1,ans[1003];//没事干的ans数组structnode{ stringop,ad;}a[1003];intws(intn){//位数 intsum=0; if(n==0)return1; while(n){ n......
  • P8816 [CSP-J 2022] 上升点列 题解
    最长上升子序列根据题目中,每个坐标的横纵坐标均单调递增,所以明显可以使用最长上升子序列.定义状态$f_{i,p}$,表示正在节点$i$时,还剩下$p$次插入机会,所能达到的最大长度.定义变量$dis=|x_i-x_j|+|y_i-y_j|-1.$,表示$i$到$j$节点至少要插$dis$个节点.为什么要$-1$......
  • ARC165F题解
    前言\(2024.10.19\)日校测\(T4\),思维太庙,被薄纱了,遂哭弱,写题解以记之。简要题意给你一个长度为\(2n\)的序列\(A,\foralla_i\in[1,n]\),其中\(1\)到\(n\)每个数都出现了两次,现在需要把相同的两个数排到一起,每次操作只能交换相邻两个数,在保证操作次数最小的情况下求出现......
  • P8814 [CSP-J 2022] 解密 题解
    解方程$题目中说,n=pq,ed=(p-1)(q-1)+1,m=n-ed+2.$$把ed的式子展开,得到:$$ed=p(q-1)-(q-1)+1$$ed=pq-p-q+2$$再把展开后的式子带入m中,得:$$m=n-(pq-p-q+2)+2.$$m=n-pq+p+q-2+2$$\becausen=pq$$\thereforem=pq-pq+p+q-2+2$$m=p+q.$$如果想要求出p和q的值,那么可以再......
  • P8815 [CSP-J 2022] 逻辑表达式 题解
    短路我们可以使用一个变量来记录当前有没有短路.设变量短路为$dl$.当$dl$为$0$时,说明当前值为$0$,且运算符为&.当$dl$为$1$时,说明当前值为$1$,且运算符为|.代码重点讲完了,细节可以看代码以及注释.#include<iostream>#include<cstdio>#include<cstring>using......
  • 最佳序列 题解
    最佳序列题解题目描述你得到了一个\(N\)个非负整数组成的序列\(A\)。我们称由序列\(A\)的连续若干项组成的新序列为\(A\)的一个连续子序列。给出两个正整数\(L,R(L\leR)\)。称\(A\)的每一个长度不小于\(L\)且不大于\(R\)的连续子序列为一个纯洁序列,定义纯洁度......
  • 题解 [NOIP2022] 建造军营
    树形\(dp\)好题。观察题目发现,如果B国袭击后,导致A国两个军营不联通,那么B国袭击的一定是一条割边,反之,如果袭击的不是割边,那么不会导致任何影响。所以先进行边双缩点,变成一棵树,记每个联通块(缩完后)内的点数为\(wa\),边数为\(wb\),不妨先考虑对于树的情况如何处理。将问题进行转......
  • 20241022 校测T1 链链链(chain)题解
    Problem链链链chain你有一个长度为\(n\)的链,编号为\(i(1≤i<n)\)的边连接着结点\(i\)与\(i+1\)。每个结点\(i\)上有一个整数\(a_i\)。你需要做以下操作\(n−1\)次:•选择一条还未被断开的边,设其连接了点\(i\)与\(i+1\),将其断开。•断边后,对于所......