[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的主要内容,如果未能解决你的问题,请参考以下文章