题目链接: http://codeforces.com/contest/1197/problem/E
题意:
你现在有 n n n 个俄罗斯套娃,每个套娃有一个外框大小 o u t [ i ] out[i] out[i] 和一个内框大小 i n [ i ] in[i] in[i] , o u t [ i ] > i n [ i ] out[i]>in[i] out[i]>in[i] ,并且他们的差就是这个套娃的厚度。套娃 i i i 可以被放进套娃 j j j 当且仅当 o u t [ i ] < = i n [ j ] out[i]<=in[j] out[i]<=in[j] 即 i i i 的外框比 j j j 的内框要小。一个套娃集合要求在可以嵌套的前提下无法再增加任一个新的套娃,一个套娃集合空心的值是任两个内外套娃边框的差值,即如果 i i i 在 j j j 之内,那么这一对空心的值就是 i n [ j ] − o u t [ i ] in[j]-out[i] in[j]−out[i] ,现在要你在空心的值最小的前提下找出有多少种套娃集合。
做法:
首先要把套娃按照关键字进行排序,按照一定的顺序进行遍历。然后,对于一个套娃集合,如果我们按照大小关系进行排序,那么我们最后的空心的值的和就是 i n x + ∑ i = 1 x − 1 o u t [ i ] − i n [ i ] in_x+\sum_{i=1}^{x-1}out[i]-in[i] inx+∑i=1x−1out[i]−in[i] ,即最大的套娃减去里面所有套娃的厚度。
我们的数据结构肯定是要包含两个信息的,一个是最小的差值,一个是当前的方案数。 O ( n 2 ) O(n^2) O(n2) 的做法是,对于每一个套娃 i i i ,我们去枚举所有内框大于它的套娃 j j j 然后不断的用差值去更新我当前这个套娃的数据,但是这样做的话复杂度肯定会炸。
所以我们就需要用一个数据结构来维护这个最优值,即在一个最小的 p o s ( i n [ p o s ] > = o u t [ i ] ) pos(in[pos]>=out[i]) pos(in[pos]>=out[i]) 下,找到 [ p o s , n ] [pos,n] [pos,n] 之中最小的空心值,并且用这个答案去维护这个线段树。如果找不到这样的 p o s pos pos,那这个套娃就只能当最大的,(注意,我们是要从后面开始做起的,这样才能保证线段树查询后方的时候有正确的值)。
这里在 p u s h U p pushUp pushUp 的时候有一个操作,因为我们要的是最小的差值,所以要把左儿子和右儿子中的那个小的值用来更新父亲,如果两个相同,那么数量就是两个的和。
代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = (int)a;i<=(int)b;i++)
#define pb push_back
#define lson rt<<1
#define rson rt<<1|1
#define mid (l+r)/2
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int maxn=200005;
const int mod=1e9+7;
const ll inf=1e9;
pll a[maxn],sum[maxn<<2];
void build(int l,int r,int rt){
sum[rt].fi=inf; sum[rt].se=0ll;
if(l==r) return ;
build(l,mid,lson);
build(mid+1,r,rson);
}
void push_up(int rt){
sum[rt]=min(sum[lson],sum[rson]);
if(sum[lson].fi==sum[rson].fi) sum[rt].se=(sum[lson].se+sum[rson].se)%mod;
}
void update(int l,int r,int rt,int p,ll cost,ll add){
if(l==r){
sum[rt].fi=cost;
sum[rt].se=add;
return ;
}
if(p<=mid) update(l,mid,lson,p,cost,add);
else update(mid+1,r,rson,p,cost,add);
push_up(rt);
}
pll deal(pll x,pll y){
pll ret=min(x,y);
if(x.fi==y.fi) ret.se=(x.se+y.se)%mod;
return ret;
}
pll query(int l,int r,int rt,int ql,int qr){
if(ql<=l&&r<=qr){
return sum[rt];
}
pll L={inf,0},R={inf,0};
if(ql<=mid) L=query(l,mid,lson,ql,qr);
if(qr>mid) R=query(mid+1,r,rson,ql,qr);
return deal(L,R);
}
int main(){
int n; scanf("%d",&n);
rep(i,1,n) {
scanf("%lld%lld",&a[i].se,&a[i].fi);
}
sort(a+1,a+1+n);
for(int i=n;i>=1;i--){
int pos=lower_bound(a+1,a+1+n,(pll){a[i].se,0})-a;
if(pos>n){
update(1,n,1,i,a[i].fi,1);
}
else{
pll ret=query(1,n,1,pos,n);
update(1,n,1,i,ret.fi-a[i].se+a[i].fi,ret.se);
}
}
pll ans=query(1,n,1,1,n);
printf("%lld\n",ans.se);
return 0;
}