传送门
莫名就跑到了 l o j r k 1 ? loj\ rk1? loj rk1?
理解不能
首先可以列出一个显然的 D P DP DP
设 f l , r , x f_{l,r,x} fl,r,x表示 [ l , r ] [l,r] [l,r]最大值为 x x x的方案数
那么显然有
f l , r , x = ∑ k , ∣ r − k + l − k ∣ ≤ 2 ( ∑ y ≤ x f l , k − 1 , x ) ( ∑ y < x f k + 1 , r , x ) f_{l,r,x}=\sum_{k,|r-k+l-k|\le2}(\sum_{y\le x}f_{l,k-1,x})(\sum_{y
考虑如果对于 A , B A,B A,B无限制时
可以归纳的得到 f l , r f_{l,r} fl,r是关于 x x x的 r − l + 1 r-l+1 r−l+1次多项式
由于 x x x太大考虑用系数表示
则转移时前缀和实际上是一个离散积分
就是求 y ≤ x y\le x y≤x时 f l , r ( y ) f_{l,r}(y) fl,r(y)用 x x x表示的和
如果直接用普通多项式求并不优秀
考虑用下降幂多项式
由于有 x j ‾ − ( x − 1 ) j ‾ = j ( x − 1 ) j − 1 ‾ x^{\underline j}-(x-1)^{\underline j}=j(x-1)^{\underline {j-1}} xj−(x−1)j=j(x−1)j−1
则 x i ‾ = ( x + 1 ) i + 1 ‾ − x i + 1 ‾ i + 1 x^{\underline i}=\frac{(x+1)^{\underline{i+1}}-x^{\underline {i+1}}}{i+1} xi=i+1(x+1)i+1−xi+1
那么 ∑ x = 1 n x i ‾ = ∑ i = 1 n ( x + 1 ) i + 1 ‾ − x i + 1 ‾ i + 1 \sum_{x=1}^nx^{\underline i}=\frac{\sum_{i=1}^n{(x+1)}^{\underline{i+1}}-x^{\underline {i+1}}}{i+1} x=1∑nxi=i+1∑i=1n(x+1)i+1−xi+1
= ( n + 1 ) i + 1 ‾ − [ i = 1 ] i + 1 =\frac{(n+1)^{\underline{i+1}}-[i=1]}{i+1} =i+1(n+1)i+1−[i=1]
则例如 ∑ i = 1 x − 1 ∑ j a j i j ‾ = ∑ j a j ∑ i = 1 x − 1 i j ‾ = ∑ j a j x j + 1 ‾ j + 1 \sum_{i=1}^{x-1}\sum_{j}a_ji^{\underline j}=\sum_ja_j\sum_{i=1}^{x-1}i^{\underline j}=\sum_ja_j\frac{x^{\underline {j+1}}}{j+1} i=1∑x−1j∑ajij=j∑aji=1∑x−1ij=j∑ajj+1xj+1
于是对于下降幂多项式可以做到 O ( n ) O(n) O(n)求前缀和
那么还需要做的就是对于下降幂多项式相加相乘
至于相乘
可以 m t t mtt mtt做到 O ( n l o g n ) O(nlogn) O(nlogn)
但是没有必要
考虑怎么做 O ( n 2 ) O(n^2) O(n2)的乘法
对于 ∑ i a i x i ‾ ∗ ∑ i b i x i ‾ \sum_i a_ix^{\underline i}*\sum_ib_ix^{\underline i} ∑iaixi∗∑ibixi
那么对于左边的 x i ‾ x^{\underline i} xi,右边应该拿 ( x − i ) j ‾ (x-i)^{\underline j} (x−i)j来乘
又有 x j ‾ − ( x − 1 ) j ‾ = j ( x − 1 ) j − 1 ‾ x^{\underline j}-(x-1)^{\underline j}=j(x-1)^{\underline {j-1}} xj−(x−1)j=j(x−1)j−1
于是可以每次 O ( n ) O(n) O(n)的将 ∑ i b i x i ‾ \sum_ib_ix^{\underline i} ∑ibixi变成 ∑ i b i ( x − 1 ) i ‾ \sum_ib_i(x-1)^{\underline i} ∑ibi(x−1)i
现在考虑有 A , B A,B A,B的限制
那么可以离散化成 O ( n ) O(n) O(n)个区间
每个区间内部的多项式是一样的
于是变成维护分段下降幂多项式
其他处理是一样的
记忆化搜索实现这个 D P DP DP
复杂度为 O ( n ∑ l , r [ 区 间 l , r 合 法 ] ( r − l + 1 ) 2 ) O(n\sum_{l,r}[区间l,r合法](r-l+1)^2) O(n∑l,r[区间l,r合法](r−l+1)2)
据说分析出来就是 O ( n 3 ) O(n^3) O(n3)的
确实跑的飞快
#include
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline ll readll(){
char ch=gc();
ll res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
return top;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
cs int N=305;
int iv[N];
inline void init_inv(){
iv[0]=iv[1]=1;
for(int i=2;i<N;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
}
typedef vector<int> poly;
inline int F(cs poly &f,int x){
int res=0;
for(int i=0,mt=1;i<f.size();Mul(mt,x-i),i++)Add(res,mul(f[i],mt));
return res;
}
inline poly operator +(poly a,poly b){
a.resize(max(a.size(),b.size()));
for(int i=0;i<b.size();i++)Add(a[i],b[i]);
return a;
}
inline poly operator *(poly a,poly b){
int deg=a.size()+b.size()-1;
poly c(deg,0);
for(int i=0;i<a.size();i++){
for(int j=0;j<b.size();j++)Add(c[i+j],mul(a[i],b[j]));
for(int j=1;j<b.size();j++)Add(b[j-1],mul(b[j],j));
}
return c;
}
inline poly integ(poly a){
a.pb(0);
for(int i=a.size()-1;i;i--)a[i]=mul(a[i-1],iv[i]);
a[0]=0;return a;
}
typedef pair<poly,int> pi;
typedef vector<pi> Poly;
inline Poly operator +(cs Poly &a,cs Poly &b){
Poly c;int i=0,j=0,lim=0;
while(0721){
c.pb(pi(a[i].fi+b[j].fi,lim));
if(i+1==a.size()&&j+1==b.size())break;
if(i+1<a.size()&&(j+1==b.size()||a[i+1].se<b[j+1].se))
lim=a[++i].se;else lim=b[++j].se;
if(i+1<a.size()&&a[i+1].se<=lim)i++;
if(j+1<b.size()&&b[j+1].se<=lim)j++;
}
return c;
}
inline Poly operator *(cs Poly &a,cs Poly &b){
Poly c;int i=0,j=0,lim=0;
while(0721){
c.pb(pi(a[i].fi*b[j].fi,lim));
if(i+1==a.size()&&j+1==b.size())break;
if(i+1<a.size()&&(j+1==b.size()||a[i+1].se<b[j+1].se))
lim=a[++i].se;else lim=b[++j].se;
if(i+1<a.size()&&a[i+1].se<=lim)i++;
if(j+1<b.size()&&b[j+1].se<=lim)j++;
}
return c;
}
inline Poly cut(cs Poly &a,int l,int r){
Poly b;b.pb(pi(poly(1),0));
for(int i=0;i<a.size();i++){
if(a[i].se<=r&&(i+1==a.size()||a[i+1].se>l))
b.pb(pi(a[i].fi,max(l,a[i].se)));
}
b.pb(pi(poly(1),r+1));
return b;
}
inline Poly integ(cs Poly &a){
Poly b;
for(int i=0;i<a.size();i++){
b.pb(pi(integ(a[i].fi),a[i].se));
if(i)b[i].fi[0]=dec(F(b[i-1].fi,a[i].se),F(b[i].fi,a[i].se));
}return b;
}
Poly f[2505];
int n,id[N][N],tot,L[N],R[N];
void dfs(int l,int r){
if(id[l][r])return;
id[l][r]=++tot;
int u=id[l][r];
f[u].pb(pi(poly(1,0),0));
if(l>r){f[u][0].fi[0]=1;return;}
for(int i=l;i<=r;i++)if(abs(r-i-(i-l))<=2){
dfs(l,i-1),dfs(i+1,r);
Poly vl=f[id[l][i-1]],vr=f[id[i+1][r]];
if(l<i)vl=vl+integ(vl);
if(i<r)vr=integ(vr);
f[u]=f[u]+cut(vl*vr,L[i],R[i]);
}
}
int main(){
freopen("robot.in","r",stdin);
freopen("robot.out","w",stdout);
n=read();
init_inv();
for(int i=1;i<=n;i++)L[i]=read(),R[i]=read();
dfs(1,n);
cout<<integ(f[id[1][n]]).back().fi[0]<<'\n';
return 0;
}