CodeForces 1197E  Culture Code(最短路/dp)_dp

CodeForces 1197E  Culture Code(最短路/dp)_#define_02

 

 

大致题意:给你n个俄罗斯套娃,告诉你每个套娃内外的半径。问你这里面有多少个集合,可以使得外层不能再套别的套娃而且里面剩余的空间最小。

这题的话想到思路还是不难的,无非是套娃的嵌套关系。如果我们找到所有的嵌套关系,我们可以考虑建立一个有向带权图。对于任意的边<u,v,w>表示第u个套娃可以套第v个套娃而且套了的话中间缝隙为w。如此,我们只需要对于这个带权有向图求一下最短路的条数就是最后的结果。但是,这题点数较多,如果这么建图时间和空间都过不去。

我们来重新考虑一下我们做最短路的过程,最短路松弛的时候本质是维护这样一个方程:

                                                   

CodeForces 1197E  Culture Code(最短路/dp)_最小值_03

化简一下这个式子可以有:

                                                   

CodeForces 1197E  Culture Code(最短路/dp)_#define_04

由于in[x]是固定的,所以我们在所有外层小于等于第x个套娃的内层的套娃里面,找一个d[y]-out[y]最小的一个。又因为内层小于外层。那么,我们显然可以对所有的套娃按照外层排序,这样我们就可以直接找到外层小于in[x]的区间求一个区间最小值即可,同时在更新的时候按照内层排序,保证满足要求的区间的d[y]都已经是有值的。如此,我们总的时间复杂度就是O(NlogN)的,可以做完此题。

但是呢,这里我们其实可以有O(N)的做法,因为我们更新d的时候是按照内层排序的,所以越往后其实这个区间是单调的,只会变大不会变小,所以只需要维护一个最小值即可,不需要重新在区间中查询。具体见代码:

#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f3f3f3f3fll
#define eps 1e-10
#define pi 3.141592653589793
#define mod 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;

struct node{int x,y;} p[N];
LL t[N],ans,d[N],mn;
int a[N],b[N],n,mx;

int main(int argc, char const *argv[])
{
sc(n);
for(int i=1;i<=n;i++)
{
scc(p[i].x,p[i].y);
a[i]=b[i]=i; mx=max(mx,p[i].y);
}
sort(a+1,a+1+n,[](int i,int j){return p[i].x<p[j].x;});
sort(b+1,b+1+n,[](int i,int j){return p[i].y<p[j].y;});
for(int i=1,j=1,tt=1;i<=n;i++)
{
int id1=b[i]; t[id1]=1;
while(j<=n&&p[a[j]].x<=p[id1].y)
{
int id2=a[j++],x=p[id2].x;
if (d[id2]-x<mn)
{
mn=d[id2]-x;
tt=t[id2];
} else if (d[id2]-x==mn) tt=(tt+t[id2])%mod;
}
d[id1]=p[id1].y+mn;
t[id1]=tt;
}
mn=INF;
for(int i=n;i>=1;i--)
{
if (p[a[i]].x<=mx) break;
if (d[a[i]]<mn) mn=d[a[i]],ans=t[a[i]];
else if (d[a[i]]==mn) ans=(ans+t[a[i]])%mod;
}
printf("%lld\n",ans);
return 0;
}