解析
打表可得,有效状态大概只有
O
(
m
)
=
O
(
n
log
n
)
O(m)=O(n\log n)
O(m)=O(nlogn) 种。
枚举最靠右的最大值位置,不难得到
O
(
m
V
)
O(mV)
O(mV) 的做法。
期望得分
50
50
50 分。
考虑如何做
l
=
0
,
r
=
1
0
9
l=0,r=10^9
l=0,r=109。,发现前缀和后所有的
d
p
i
,
i
,
x
=
x
dp_{i,i,x}=x
dpi,i,x=x,可以看成一个
1
1
1 次多项式。
归纳的,
d
p
l
,
r
dp_{l,r}
dpl,r 转移的时候从
d
p
l
,
i
−
1
∗
d
p
i
+
1
,
r
dp_{l,i-1}*dp_{i+1,r}
dpl,i−1∗dpi+1,r 得到,是一个
r
−
l
r-l
r−l 次多项式,再前缀和后,又变成了
r
−
l
+
1
r-l+1
r−l+1 次的多项式。
直接插值即可。
那么当值域不相同时,离散化后变成了 O ( n ) O(n) O(n) 段,对每段单独做时,小于当前段的影响就变成了常数,所以还是可以插值的。
每段复杂度
O
(
n
m
)
O(nm)
O(nm),故总复杂度
O
(
n
2
m
)
O(n^2m)
O(n2m)。
需要一定卡常。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("ok\n")
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
bool mem1;
const int N=305;
const int S=2250;
const int mod=1e9+7;
inline ll ksm(ll x,ll k){
ll res(1);
while(k){
if(k&1) res=res*x%mod;
x=x*x%mod;
k>>=1;
}
return res;
}
#define add(x,y) ((((x)+=(y))>=mod)&&((x)-=mod))
int n,m;
int id[N][N],tot;
int dp[S][N],le[S],ri[S];
int a[N],b[N],q[N<<1],cnt;
void init(int l,int r){
if(l>r){
//dp[tot][0]=1;
//jd[tot]=1;
return;
}
if(id[l][r]) return;
//printf("(%d %d) id=%d\n",l,r,id[l][r]);
for(int i=l;i<=r;i++){
if(abs((i-l)-(r-i))<=2){
init(l,i-1);
init(i+1,r);
}
}
id[l][r]=++tot;
le[tot]=l;
ri[tot]=r;
return;
}
int now,p;
int jc[N],ni[N],pre[N],suf[N],pi[N];
#define calc(i) (1ll*w[i]*pi[i])
inline int lagrange(int *w,int l,int r,int x){
int ans(0),ans1(0),ans2(0),ans3(0),ans4(0),ans5(0),ans6(0),ans7(0),ans8(0),i=1;
for(;i+8<=r-l+1;i+=8){
if((r-l+1-i)&1){
add(ans1,mod-calc(i)%mod);
add(ans3,mod-calc(i+2)%mod);
add(ans5,mod-calc(i+4)%mod);
add(ans7,mod-calc(i+6)%mod);
ans2=(ans2+calc(i+1))%mod;
ans4=(ans4+calc(i+3))%mod;
ans6=(ans6+calc(i+5))%mod;
ans8=(ans8+calc(i+7))%mod;
}
else{
add(ans2,mod-calc(i+1)%mod);
add(ans4,mod-calc(i+3)%mod);
add(ans6,mod-calc(i+5)%mod);
add(ans8,mod-calc(i+7)%mod);
ans1=(ans1+calc(i))%mod;
ans3=(ans3+calc(i+2))%mod;
ans5=(ans5+calc(i+4))%mod;
ans7=(ans7+calc(i+6))%mod;
}
}
for(;i<=r-l+1;i++){
//if((r-l+1-i)&1) add(ans1,mod-calc(i));
//else add(ans1,calc(i));
if((r-l+1-i)&1) add(ans,mod-calc(i)%mod);
else ans=(ans+calc(i))%mod;
}
add(ans,ans1);
add(ans,ans2);
add(ans,ans3);
add(ans,ans4);
add(ans,ans5);
add(ans,ans6);
add(ans,ans7);
add(ans,ans8);
//for(int i=1;i<=r-l+1;i++) printf(" i=%d w=%lld\n",i,w[i]);
//printf(" x=%d ans=%lld\n",x,ans);
return ans;
}
void work(int len){
now=min(len,n+1);
for(int i=0;i<=now;i++) dp[0][i]=1;
for(int x=1;x<=tot;x++){
int l=le[x],r=ri[x];
if((r-l+1)%2){
for(int i=max(l,(l+r)/2-1);i<=min(r,(l+r)/2+1);i++){
//solve(l,i-1);
//solve(i+1,r);
if(a[i]<=p&&p<b[i]){
//printf(" i=%d\n",i);
int j=1;
for(;j+4<=now;j+=4){
dp[x][j]=(dp[x][j]+1ll*dp[id[l][i-1]][j]*dp[id[i+1][r]][j-1])%mod;
dp[x][j+1]=(dp[x][j+1]+1ll*dp[id[l][i-1]][j+1]*dp[id[i+1][r]][j+1-1])%mod;
dp[x][j+2]=(dp[x][j+2]+1ll*dp[id[l][i-1]][j+2]*dp[id[i+1][r]][j+2-1])%mod;
dp[x][j+3]=(dp[x][j+3]+1ll*dp[id[l][i-1]][j+3]*dp[id[i+1][r]][j+3-1])%mod;
}
for(;j<=now;j++){
//add(dp[x][j],1ll*dp[id[l][i-1]][j]*dp[id[i+1][r]][j-1]%mod);
dp[x][j]=(dp[x][j]+1ll*dp[id[l][i-1]][j]*dp[id[i+1][r]][j-1])%mod;
}
}
}
}
else{
for(int i=(l+r)/2;i<=(l+r)/2+1;i++){
//solve(l,i-1);
//solve(i+1,r);
if(a[i]<=p&&p<b[i]){
//printf(" i=%d\n",i);
int j=1;
for(;j+4<=now;j+=4){
add(dp[x][j],1ll*dp[id[l][i-1]][j]*dp[id[i+1][r]][j-1]%mod);
add(dp[x][j+1],1ll*dp[id[l][i-1]][j+1]*dp[id[i+1][r]][j+1-1]%mod);
add(dp[x][j+2],1ll*dp[id[l][i-1]][j+2]*dp[id[i+1][r]][j+2-1]%mod);
add(dp[x][j+3],1ll*dp[id[l][i-1]][j+3]*dp[id[i+1][r]][j+3-1]%mod);
}
for(;j<=now;j++){
add(dp[x][j],1ll*dp[id[l][i-1]][j]*dp[id[i+1][r]][j-1]%mod);
}
}
}
}
for(int i=1;i<=now;i++){
add(dp[x][i],dp[x][i-1]);
}
}
if(len>n+1){
int x=q[p+1]-1,l=q[p],r=q[p]+now-1;
pre[0]=1;
for(int i=1;i<=r-l+1;i++) pre[i]=1ll*pre[i-1]*(x-(l+i-1))%mod;
suf[r-l+1+1]=1;
for(int i=r-l+1;i>=1;i--){
suf[i]=1ll*suf[i+1]*(x-(l+i-1))%mod;
pi[i]=1ll*pre[i-1]%mod*suf[i+1]%mod*ni[i-1]%mod*ni[r-l+1-(i)]%mod;
}
}
for(int i=1;i<=tot;i++){
if(len<=n+1) dp[i][0]=dp[i][now];
else{
dp[i][0]=lagrange(dp[i],q[p],q[p]+now-1,q[p+1]-1);
}
//printf(" i=%d dp=%lld\n",i,dp[i][0]);
//for(int j=1;j<=now;j++) dp[i][j]=0;
memset(dp[i]+1,0,sizeof(int)*(now));
}
return;
}
bool mem2;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
debug("mem=%.2lf\n",abs(&mem2-&mem1)/1024./1024);
n=read();
jc[0]=1;
for(int i=1;i<=n;i++) jc[i]=1ll*jc[i-1]*i%mod;
ni[n]=ksm(jc[n],mod-2);
for(int i=n-1;i>=0;i--) ni[i]=1ll*ni[i+1]*(i+1)%mod;
for(int i=1;i<=n;i++){
q[++cnt]=a[i]=read();
q[++cnt]=b[i]=read()+1;
}
sort(q+1,q+1+cnt);
cnt=unique(q+1,q+1+cnt)-q-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(q+1,q+1+cnt,a[i])-q;
b[i]=lower_bound(q+1,q+1+cnt,b[i])-q;
}
init(1,n);
debug("tot=%d\n",tot);
for(int i=1;i<cnt;i++){
p=i;
//printf("\np=%d [%d %d)\n",p,q[i],q[i+1]);
work(q[i+1]-q[i]);
}
printf("%d\n",dp[id[1][n]][0]);
return 0;
}