传送门
d
p
[
i
]
[
j
]
[
i
d
]
dp[i][j][id]
dp[i][j][id]表示有
i
i
i段,现在以第
j
j
j个点结尾。
i
d
=
0
id=0
id=0表示最后上升,
i
d
=
1
id=1
id=1表示最后下降。
有转移方程:
d
p
[
i
]
[
j
]
[
0
]
=
∑
k
=
i
+
1
j
−
1
∑
y
[
k
]
<
y
[
j
]
d
p
[
i
]
[
k
]
[
0
]
+
∑
k
=
i
j
−
1
∑
y
[
k
]
<
y
[
j
]
d
p
[
i
−
1
]
[
k
]
[
1
]
dp[i][j][0]=\sum_{k=i+1}^{j-1}\sum_{y[k]<y[j]}dp[i][k][0]+\sum_{k=i}^{j-1}\sum_{y[k]<y[j]}dp[i-1][k][1]
dp[i][j][0]=k=i+1∑j−1y[k]<y[j]∑dp[i][k][0]+k=i∑j−1y[k]<y[j]∑dp[i−1][k][1]
d
p
[
i
]
[
j
]
[
1
]
=
∑
k
=
i
+
1
j
−
1
∑
y
[
k
]
>
y
[
j
]
d
p
[
i
]
[
k
]
[
1
]
+
∑
k
=
i
j
−
1
∑
y
[
k
]
>
y
[
j
]
d
p
[
i
−
1
]
[
k
]
[
0
]
dp[i][j][1]=\sum_{k=i+1}^{j-1}\sum_{y[k]>y[j]}dp[i][k][1]+\sum_{k=i}^{j-1}\sum_{y[k]>y[j]}dp[i-1][k][0]
dp[i][j][1]=k=i+1∑j−1y[k]>y[j]∑dp[i][k][1]+k=i∑j−1y[k]>y[j]∑dp[i−1][k][0]
用四个树状数组维护这四个和。
先枚举
i
i
i,然后
j
j
j枚举完后把树状数组清空,
i
i
i增加。
i
i
i和
i
−
1
i-1
i−1递推用滚动数组实现。
注意开始时要加上
d
p
[
i
−
1
]
[
i
]
[
0
/
1
]
dp[i-1][i][0/1]
dp[i−1][i][0/1]的贡献。
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
const int mod=1e5+7;const int maxn=5e4+10;const int oo=1e5;
int dp[12][maxn][2],tr[oo+10][2][2],n,k,ans=0;
inline void add(int x,int v,int id,int di){for(int i=x;i<=oo;i+=lowbit(i)) tr[i][id][di]=(tr[i][id][di]+v)%mod;}
inline int query(int x,int id,int di,int ret=0){for(int i=x;i>=1;i-=lowbit(i)) ret=ret+tr[i][id][di];return ret%mod;}
inline int read(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
struct point{
int x,y;
friend inline bool operator<(point a,point b){return a.x<b.x;}
}a[maxn];
int main(){
n=read(),k=read();
for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read();
sort(a+1,a+n+1);
for(int i=1;i<=n;++i) dp[0][i][0]=dp[0][i][1]=1;
for(int i=1;i<=k;++i){
memset(tr,0,sizeof(tr));
add(a[i].y,dp[i-1][i][0],(i-1)&1,0);
add(a[i].y,dp[i-1][i][1],(i-1)&1,1);
for(int j=i+1;j<=n;++j){
dp[i][j][0]=(query(a[j].y-1,i&1,0)+query(a[j].y-1,(i-1)&1,1))%mod;
dp[i][j][1]=(query(oo,(i-1)&1,0)-query(a[j].y,(i-1)&1,0)+query(oo,i&1,1)-query(a[j].y,i&1,1)+mod)%mod;
add(a[j].y,dp[i][j][0],i&1,0);
add(a[j].y,dp[i-1][j][0],(i-1)&1,0);
add(a[j].y,dp[i][j][1],i&1,1);
add(a[j].y,dp[i-1][j][1],(i-1)&1,1);
}
}
for(int i=1;i<=n;++i) ans=(ans+dp[k][i][0]+dp[k][i][1])%mod;
printf("%d\n",ans);
}