E Culture Code
题意:
给定n个布偶,每一个布偶有内部空间 i n [ i ] in[i] in[i],外部体积 o u t [ i ] out[i] out[i],如果 i n [ i ] > = o u t [ j ] in[i] >= out[j] in[i]>=out[j],我们就可以将j套入到i里面,定义一个最打集合嵌套是使得没有再有新的布偶可以加入到这个集合中嵌套进去。我们定义一个集合的cost是浪费的空间,问使得cost最小的集合的数量是多少?
分析:
- 首先考虑怎么求最小代价,我们可以将嵌套想象成一个有向无环图,在有向无环图上跑,肯定是dp比较合适,关键是我们不能直接建图,因为数据范围太大了,我们发现具有单调性,就是如果 i n [ i ] > = i n [ j ] in[i] >= in[j] in[i]>=in[j]那么可以嵌套进 j j j的一定可以嵌套进去 i i i,所以我们考虑前缀的思想,一步步地推。
- 对所有的布偶按 i n [ i ] in[i] in[i]排序,对所有的布偶按 o u t [ i ] out[i] out[i]排序,按 o u t [ i ] out[i] out[i]排序是为了便于统计布偶的贡献,因为 o u t [ i ] < = i n [ j ] out[i] <= in[j] out[i]<=in[j],排序之后,就可以嵌套,那么如果已经排序 对于所有的 1 < = k < i 1 <= k < i 1<=k<i都可以嵌套
- 每一次的最小值怎么递推呢,考虑上一个 i n p r e < i n n o w in_{pre} < in_{now} inpre<innow, 由于 关于 i n p r e in_{pre} inpre的最小值已经统计出来,那么我把相同的木偶嵌套金 i n n o w in_{now} innow, m i n c o s t mincost mincost增加了 i n n o w − i n p r e in_{now}-in_{pre} innow−inpre,之后再考虑加入之前不能加入的娃娃,依次更新当前的最小值,并且将计数的值更新
- 最后统计所有不能再嵌套的木偶的最小值以及贡献即可
参考代码
const int maxn = 4e5+10;
int out[maxn],in[maxn];
int q[maxn],p[maxn];
LL dp[maxn],num[maxn];
// dp[i] 代表in第i小的最小空间,num[i] 代表计数
/*
dp[i] 满足前一个对后一个的贡献可以加入,如果出现更小的,可以更新
*/
int main(void)
{
int n;
cin>>n;
int maxin = 0;
for(int i= 1;i <= n;++i){
scanf("%d%d",&out[i],&in[i]);
q[i] = p[i] = i;
maxin = max(maxin,in[i]);
}
// cout<<endl;
// DEBUG;
sort(q+1,q+n+1,[](const int &a,const int &b){return out[a] < out[b];});
sort(p+1,p+n+1,[](const int &a,const int &b){return in[a] < in[b];});
int j = 1;
int delta = 0;
int sum = 0;// 前缀和计算贡献
for(int i = 1;i <= n; ++i){
delta = in[p[i]]-in[p[i-1]]+delta;
while(j <= n && out[q[j]] <= in[p[i]]){
int d = in[p[i]]-out[q[j]]+dp[q[j]];
if(d == delta)
(sum+=num[q[j]])%=mod;
else if(d < delta)
delta = d,sum = num[q[j]];
++j;
}
dp[p[i]] = delta;
num[p[i]] = max(sum,1);
// cout<<i<<" "<<"in "<<dp[p[i]]<<endl;
}
// cout<<delta<<endl;
sum = 0;
for(int i = 1;i <= n; ++i){
if(out[i] > maxin)
{
if(dp[i] < delta)
delta = dp[i],sum = num[i];
else if(dp[i] == delta)
(sum+=num[i])%=mod;
}
}
// cout<<delta<<endl;
cout<<sum<<endl;
return 0;
}
```cpp