[CF1534F1/2]Falling Sand

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1534F1/2]Falling Sand相关的知识,希望对你有一定的参考价值。

Falling Sand

题解

About F1

首先我们应该很容易想到建图。
对于一个沙子,向它左,右,上,下四个方向能影响到的最近的沙子连边,很明显,通过这些方块总存在一条到其它能影响到的沙子。
我们要找的,就是选择尽量少的沙子使得它将所有点都覆盖到。
但这连出来的图是存在环的,环内的沙子是会互相影响的。
这是我们就需要缩点了,缩点后得到的无环有向图,选择所有入度为零的沙子即可。
时间复杂度 O ( n m ) O\\left(nm\\right) O(nm)

About F2

对于这个图,我们只需要让第 i i i列的第 a i a_{i} ai块掉下来即可,它们掉了,下面的自然也会掉。
我们还是先建图,跑tarjan缩点。
但对于包含第 i i i列第 a i a_{i} ai个的,我们称其为关键点。我们的目的就是让所有的关键点都掉下去。
对于可以被其它关键点走到的关键点,是没有意义的,我们可以不管它们。

之后我们可以发现,对于任何一个点,它能够走到的关键点的区间是连续的。
如果存在 i < j < k i<j<k i<j<k使得 i i i列与 k k k列的对应的关键点能被走到,但 j j j列不能。那么 i i i列与 k k k列一定可以通过 j j j列中的一个点联通。
如果这个点在 j j j列的关键点之下,那么 j j j列的关键点必然可以影响到 i i i列与 k k k列中的一个关键点。
如果这个点在 j j j列的关键点之上,那么 j j j列的关键点必然可以被 i i i列或 k k k列中的一个关键点影响到。
无论怎么都不满足我们的条件,所以其对应的区间必定是连续的。

所以我们可以先通过拓扑求出每个点对应的区间,然后将所有的区间按左端点排序,贪心选出最少的区间使其覆盖所有关键点即可。

时间复杂度 O ( n m l o g   n m ) O\\left(nmlog\\,nm\\right) O(nmlognm)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 400005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int iv2=5e8+4;
const int lim=1000000;
const int jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int n,m,a[MAXN],head[MAXN],dfn[MAXN],low[MAXN],cnt,idx,deg[MAXN];
int sta[MAXN],stak,tot,num,belong[MAXN],ans,p[MAXN],ord[MAXN];
bool insta[MAXN],key[MAXN],loged[MAXN];char maze[MAXN];
vector<int>s[MAXN],Id[MAXN],G[MAXN];
queue<int> q;
struct edge{int to,nxt;}e[MAXN<<2];
struct range{int l,r;}sd[MAXN];
inline void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
bool cmp(range x,range y){return x.l<y.l;}
void tarjan(int x){
	dfn[x]=low[x]=++idx;sta[++stak]=x;insta[x]=1;
	for(reg int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;
		if(!dfn[v])tarjan(v),low[x]=min(low[x],low[v]);
		else if(insta[v])low[x]=min(low[x],dfn[v]);
	}
	if(low[x]==dfn[x]){int v;++num;do{v=sta[stak--];insta[v]=0;belong[v]=num;}while(v!=x);}
}
void sakura(){
	while(!q.empty())q.pop();int nm=0;
	for(reg int i=1;i<=num;i++)if(!deg[i])q.push(i);
	for(reg int i=1;i<=m;i++)if(p[i]&&key[p[i]])loged[p[i]]=1;
	while(!q.empty()){
		int t=q.front();q.pop();ord[++nm]=t;
		for(reg int i=0;i<(int)G[t].size();i++){
			int v=G[t][i];deg[v]--;if(!deg[v])q.push(v);
			if(loged[t])loged[v]=1,key[v]=0;
		}
	}
	for(reg int i=1;i<=num;i++)sd[i].l=INF;
	for(reg int i=1;i<=m;i++)if(p[i]&&key[p[i]])
		sd[p[i]].l=min(i,sd[p[i]].l),sd[p[i]].r=max(sd[p[i]].r,i);
	for(reg int i=num;i>0;i--)
		for(reg int j=0;j<(int)G[ord[i]].size();j++)
			sd[ord[i]].l=min(sd[ord[i]].l,sd[G[ord[i]][j]].l),
			sd[ord[i]].r=max(sd[ord[i]].r,sd[G[ord[i]][j]].r);
}
signed main(){
	read(n);read(m);
	for(reg int i=1;i<=n;i++){
		scanf("%s",maze+1);
		for(reg int j=1;j<=m;j++)if(maze[j]=='#')
			s[j].push_back(i),Id[j].push_back(++cnt);
	}
	for(reg int i=1;i<=m;i++)read(a[i]);
	for(reg int i=1;i<=m;i++)
		for(reg int j=0;j<(int)s[i].size();j++){
			if(!s[i-1].empty()&&s[i][j]<=s[i-1][s[i-1].size()-1]){
				int l=0,r=s[i-1].size()-1;
				while(l<r){int mid=l+r>>1;if(s[i-1][mid]>=s[i][j])r=mid;else l=mid+1;}
				addEdge(Id[i][j],Id[i-1][l]);
			}
			if(!s[i+1].empty()&&s[i][j]<=s[i+1][s[i+1].size()-1]){
				int l=0,r=s[i+1].size()-1;
				while(l<r){int mid=l+r>>1;if(s[i+1][mid]>=s[i][j])r=mid;else l=mid+1;}
				addEdge(Id[i][j],Id[i+1][l]);
			}
			if(j<(int)s[i].size()-1)addEdge(Id[i][j],Id[i][j+1]);
			if(j>0&&s[i][j-1]+1==s[i][j])addEdge(Id[i][j],Id[i][j-1]); 
		}
	for(reg int i=1;i<=cnt;i++)if(!dfn[i])tarjan(i);
	for(reg int i=1;i<=m;i++){
		int t=s[i].size()-a[i];
		if(0<=t&&t<(int)s[i].size())
			p[i]=belong[Id[i][t]]<

以上是关于[CF1534F1/2]Falling Sand的主要内容,如果未能解决你的问题,请参考以下文章

CF1534C Little Alawn's Puzzle

[CF1534G]A New Beginning

cf670E Correct Bracket Sequence Editor

UVA 699 The Falling Leaves

POJ 1577 Falling Leaves

699. Falling Squares