​传送门​​​[NOI2019] 机器人[DP] [拉格朗日插值]_#define 的第5道,听说可以用下降幂维护,但是我用拉格朗日插值怼过去了
考虑暴力的[NOI2019] 机器人[DP] [拉格朗日插值]_git_02[NOI2019] 机器人[DP] [拉格朗日插值]_#define_03表示区间 [NOI2019] 机器人[DP] [拉格朗日插值]_git_04 的最大值为 [NOI2019] 机器人[DP] [拉格朗日插值]_i++_05 的方案数
枚举最高点位置,显然并没有东西可以挡住最高点,因此
如果区间为奇数,[NOI2019] 机器人[DP] [拉格朗日插值]_i++_06
如果区间为偶数,[NOI2019] 机器人[DP] [拉格朗日插值]_git_07
[NOI2019] 机器人[DP] [拉格朗日插值]_i++_08
然后发现 [NOI2019] 机器人[DP] [拉格朗日插值]_git_09 每次取的值很少,于是总的区间个数[NOI2019] 机器人[DP] [拉格朗日插值]_i++_10应该不会很多
于是就有[NOI2019] 机器人[DP] [拉格朗日插值]_#define_11 的算法
考虑 [NOI2019] 机器人[DP] [拉格朗日插值]_git_12 ,转移十分的单一,猜想它是一个关于 [NOI2019] 机器人[DP] [拉格朗日插值]_i++_05 的多项式
首先对于 [NOI2019] 机器人[DP] [拉格朗日插值]_i++_14[NOI2019] 机器人[DP] [拉格朗日插值]_#define_15 是一个常数,然后每次将 [NOI2019] 机器人[DP] [拉格朗日插值]_#define_15 前缀和后加起来就会多一次,两边乘起来次数相当与加起来,[NOI2019] 机器人[DP] [拉格朗日插值]_#define_15 是一个不超过 [NOI2019] 机器人[DP] [拉格朗日插值]_#define_18 次的多项式
考虑先按权值排序,分段,[NOI2019] 机器人[DP] [拉格朗日插值]_i++_19 的转移类似 [NOI2019] 机器人[DP] [拉格朗日插值]_git_12
我们只需要暴力维护 [NOI2019] 机器人[DP] [拉格朗日插值]_git_21[NOI2019] 机器人[DP] [拉格朗日插值]_git_02 的值,然后可以通过拉格朗日插出 [NOI2019] 机器人[DP] [拉格朗日插值]_i++_23[NOI2019] 机器人[DP] [拉格朗日插值]_git_02
复杂度 [NOI2019] 机器人[DP] [拉格朗日插值]_git_25[NOI2019] 机器人[DP] [拉格朗日插值]_git_26[NOI2019] 机器人[DP] [拉格朗日插值]_git_27可以A

#include<bits/stdc++.h>
#define N 305
#define M 3005
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
while(isdigit(ch)) cnt = (cnt << 1) + (cnt << 3) + (ch-'0'), ch = getchar();
return cnt * f;
}
#define cs const
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b;}
int mul(int a, int b){ return 1ll * a * b % Mod;}
int power(int a, int b){int ans=1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans=mul(ans,a); return ans;}
void Add(int &a, int b){ a = add(a, b);}

int home[N][N], dp[M][N], len[M];
bool vis[N][N];
int n, m, bench, a[N], b[N];
int e[N << 1], tot, Max;
int lim, x[N]; // lagrange
int fac[N], inv[N];
void prework(){
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for(int i = 2; i <= lim; i++) fac[i] = mul(fac[i-1], i);
inv[lim] = power(fac[lim], Mod-2);
for(int i = lim-1; i >= 2; i--) inv[i] = mul(inv[i+1], i+1);
}
void get(int now, int l, int r, int cur);
int work(int l, int r){
if(l > r || vis[l][r]) return home[l][r];
int mid = (l+r) >> 1;
if(home[l][r] == 0){
home[l][r] = ++m;
len[m] = r-l+1;
} int now = home[l][r];
for(int i = 1; i <= Max; i++) dp[now][i] = 0;
if(l == r){
for(int i = 1; i <= Max; i++)
dp[now][i] = dp[now][i-1] + (i + bench >= a[l] && i + bench <= b[l]);
return now;
}
if(mid - l == r - mid){ get(now, l, r, mid - 1); get(now, l, r, mid); get(now, l, r, mid + 1); }
else{ get(now, l, r, mid); get(now, l, r, mid + 1);}
for(int i = 1; i <= Max; i++) Add(dp[now][i], dp[now][i-1]);
vis[l][r] = 1;
return now;
}
void get(int now, int l, int r, int cur){
int u = work(l, cur - 1), v = work(cur + 1, r);
for(int i = 1; i <= Max; i++)
if(i + bench >= a[cur] && i + bench <= b[cur])
Add(dp[now][i], mul(dp[u][i], dp[v][i-1]));
}
int lagrange(int n, int *x, int *y, int pos){
static int pre[N], suf[N];
pre[0] = add(pos, Mod - x[0]);
suf[n] = add(pos, Mod - x[n]);
for(int i = 1; i <= n; i++) pre[i] = mul(pre[i-1], add(pos, Mod - x[i]));
for(int i = n-1; i >= 0; i--) suf[i] = mul(suf[i+1], add(pos, Mod - x[i]));
int ans = 0;
for(int i = 0; i <= n; i++){
int tmp = 1;
if(i) tmp = mul(tmp, mul(inv[i], pre[i-1]));
if(i^n) tmp = mul(tmp, mul(inv[n-i], suf[i+1]));
if((n-i) & 1) tmp = Mod - tmp; ans = add(ans, mul(y[i], tmp));
} return ans;
}
int main(){
n = read(); lim = n + 3; prework();
for(int i = 1; i <= n; i++){
a[i] = read(), b[i] = read();
Max = max(Max, b[i]);
e[++tot] = a[i], e[++tot] = b[i] + 1;
} sort(e + 1, e + tot + 1);
for(int i = 0; i <= lim; i++) dp[0][i] = 1;
for(int i = 1; i <= tot; i++){
if(e[i] != e[i-1]){
bench = e[i-1];
Max = min(lim, e[i] - e[i-1] - 1);
memset(vis, 0, sizeof(vis));
work(1, n);
if(Max == e[i] - e[i-1] - 1){
for(int j = 1; j <= m; j++)
dp[j][0] = dp[j][Max];
} else{
static int x[N];
for(int j = 0; j <= lim; j++)
x[j] = bench + j;
for(int j = 1; j <= m; j++){
dp[j][0] = lagrange(len[j] + 2, x, dp[j], e[i] - 1);
}
} bench = e[i] - 1; Max = 1;
memset(vis, 0, sizeof(vis));
work(1, n);
for(int j = 1; j <= m; j++)
dp[j][0] = dp[j][Max];
}
} cout << dp[home[1][n]][0]; return 0;
}