解析
打表可得,有效状态大概只有 O(m)=O(nlogn)O(m)=O(n\log n)O(m)=O(nlogn) 种。
枚举最靠右的最大值位置,不难得到 O(mV)O(mV)O(mV) 的做法。
期望得分 505050 分。
考虑如何做 l=0,r=109l=0,r=10^9l=0,r=109。,发现前缀和后所有的 dpi,i,x=xdp_{i,i,x}=xdpi,i,x=x,可以看成一个 111 次多项式。
归纳的,dpl,rdp_{l,r}dpl,r 转移的时候从 dpl,i−1∗dpi+1,rdp_{l,i-1}*dp_{i+1,r}dpl,i−1∗dpi+1,r 得到,是一个 r−lr-lr−l 次多项式,再前缀和后,又变成了 r−l+1r-l+1r−l+1 次的多项式。
直接插值即可。
那么当值域不相同时,离散化后变成了 O(n)O(n)O(n) 段,对每段单独做时,小于当前段的影响就变成了常数,所以还是可以插值的。
每段复杂度 O(nm)O(nm)O(nm),故总复杂度 O(n2m)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_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifdebug("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;
}