HDU多校4 - 6992 Lawn of the Dead(线段树+模拟)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU多校4 - 6992 Lawn of the Dead(线段树+模拟)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出一个 n ∗ m n*m nm 的矩阵,有 k k k 个点被 b a n ban ban 掉了,现在从点 ( 1 , 1 ) (1,1) (1,1) 出发,只能向右或向下移动,问可以到达的点有多少个

题目分析:

先做一些定义,定义无法到达的点为“坏点”,可以到达的点为“好点”

虽然 n ∗ m n*m nm 很大,不能直接 b f s bfs bfs,但是单独的 n n n m m m 却不大,这里我从列入手,考虑相邻的两列,假设 p r e pre pre 为上一列的状态,现在考虑 c u r cur cur 的情况。对于第 c u r cur cur 列的每个“坏点”来说,设其横坐标为 x x x,我们需要找到第 p r e pre pre 列中,行区间 [ x + 1 , n ] [x+1,n] [x+1,n] 中的首个“好点”的位置记为 p p p,不难看出, c u r cur cur 列中的行区间 [ x , p − 1 ] [x,p-1] [x,p1] 这段都是无法到达的“坏点”。还有一种情况就是 p p p 不存在,也就是 p r e pre pre 列的行区间 [ x + 1 , n ] [x+1,n] [x+1,n] 这段都是“坏点”,那么显然 c u r cur cur 列中行区间为 [ x , n ] [x,n] [x,n] 的点也是无法到达的

区间修改、区间查找某个数字首次出现的位置,用线段树很容易就能实现了,时间复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

需要注意的是,每一列的第 0 0 0 行也要视为一个坏点

代码:

// Problem: Lawn of the Dead
// Contest: Virtual Judge - HDU
// URL: https://vjudge.net/problem/HDU-6992
// Memory Limit: 262 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
struct Seg {
	struct Node {
		int l,r,len,sum,lazy;
	}tree[N<<2];
	void pushup(int k) {
		tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
	}
	void pushdown(int k) {
		if(tree[k].lazy!=-1) {
			int lz=tree[k].lazy;
			tree[k].lazy=-1;
			tree[k<<1].lazy=tree[k<<1|1].lazy=lz;
			tree[k<<1].sum=tree[k<<1].len*lz;
			tree[k<<1|1].sum=tree[k<<1|1].len*lz;
		}
	}
	void build(int k,int l,int r) {
		tree[k]={l,r,r-l+1,0,-1};
		if(l==r) {
			return;
		}
		int mid=(l+r)>>1;
		build(k<<1,l,mid);
		build(k<<1|1,mid+1,r);
	}
	void update(int k,int l,int r,int val) {
		if(tree[k].l>r||tree[k].r<l) {
			return;
		}
		if(tree[k].l>=l&&tree[k].r<=r) {
			tree[k].lazy=val;
			tree[k].sum=tree[k].len*val;
			return;
		}
		pushdown(k);
		update(k<<1,l,r,val);
		update(k<<1|1,l,r,val);
		pushup(k);
	}
	int query_sum(int k,int l,int r) {
		if(tree[k].l>r||tree[k].r<l) {
			return 0;
		}
		if(tree[k].l>=l&&tree[k].r<=r) {
			return tree[k].sum;
		}
		pushdown(k);
		return query_sum(k<<1,l,r)+query_sum(k<<1|1,l,r);
	}
	int query(int k,int l,int r) {
		if(l>r||query_sum(k,l,r)==0) {
			return -1;
		}
		if(tree[k].l==tree[k].r) {
			return tree[k].l;
		}
		pushdown(k);
		if(query_sum(k<<1,l,r)) {
			return query(k<<1,l,r);
		} else {
			return query(k<<1|1,l,r);
		}
	}
}t[2];
vector<int>node[N];
int main()
{
#ifndef ONLINE_JUDGE
//	freopen("data.in.txt","r",stdin);
//	freopen("data.out.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--) {
		int n,m,k;
		read(n),read(m),read(k);
		for(int i=1;i<=m;i++) {
			node[i].clear();
			node[i].push_back(0);
		}
		while(k--) {
			int x,y;
			scanf("%d%d",&x,&y);
			node[y].push_back(x);
		}
		LL ans=0;
		t[0].build(1,1,n),t[1].build(1,1,n);
		sort(node[1].begin(),node[1].end());
		if(node[1].size()>1) {
			t[1].update(1,1,node[1][1]-1,1);
		} else {
			t[1].update(1,1,n,1);
		}
		ans+=t[1].tree[1].sum;
		for(int i=2;i<=m;i++) {
			int cur=i&1,pre=cur^1;
			t[cur].update(1,1,n,1);
			for(auto it:node[i]) {
				int p=t[pre].query(1,it+1,n);
				if(p==-1) {
					t[cur].update(1,it,n,0);
				} else {
					t[cur].update(1,it,p-1,0);
				}
			}
			ans+=t[cur].tree[1].sum;
		}
		printf("%lld\\n",ans);
	}
	return 0;
}

以上是关于HDU多校4 - 6992 Lawn of the Dead(线段树+模拟)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5381 The sum of gcd 2015多校联合训练赛#8莫队算法

Lawn of the Dead

2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP

hdu多校第4场 B Harvest of Apples(莫队)

hdu4930 Fighting the Landlords(模拟 多校6)

HDU多校4 - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?!(单调栈)