解题思路:
设
f[i][j][0/1]
表示到第
i
个点,已有
f[i][j][0]=∑(f[k][j][0]+f[k][j−1][1])(k<i,a[k].y>a[i].y)
f[i][j][1]=∑(f[k][j][1]+f[k][j−1][0])(k<i,a[k].y<a[i].y))
这个可以用树状数组优化转移。
先将y坐标离散化。
树状数组
t[j][0/1].s[k]
表示有
j
段,最后一个点的
每次加进一个点按方程更新即可。
最后答案即是
t[m][0].query(n)+t[m][1].query(n)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=50005,mod=100007;
int n,m,b[N];
struct point
{
int x,y;
inline friend bool operator < (const point &a,const point &b){return a.x<b.x;}
}a[N];
struct BIT
{
int s[N];
inline void add(int x,int y)
{
y=(y+mod)%mod;
for(int i=x;i<=n;i+=i&(-i))s[i]=(s[i]+y)%mod;
}
inline int query(int x)
{
int res=0;
for(int i=x;i;i-=i&(-i))res=(res+s[i])%mod;
return res;
}
}t[11][2];
bool cmp(const int &i,const int &j){return a[i].y<a[j].y;}
int main()
{
//freopen("lx.in","r",stdin);
n=getint(),m=getint();
for(int i=1;i<=n;i++)a[i].x=getint(),a[i].y=getint();
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)b[i]=i;
sort(b+1,b+n+1,cmp);
for(int i=1;i<=n;i++)a[b[i]].y=i;
for(int i=1;i<=n;i++)
{
t[0][0].add(a[i].y,1),t[0][1].add(a[i].y,1);
for(int j=1;j<=m;j++)
{
t[j][0].add(a[i].y,t[j][0].query(n)-t[j][0].query(a[i].y)+t[j-1][1].query(n)-t[j-1][1].query(a[i].y));
t[j][1].add(a[i].y,t[j][1].query(a[i].y-1)+t[j-1][0].query(a[i].y-1));
}
}
printf("%d",(t[m][0].query(n)+t[m][1].query(n))%mod);
}