二维平面上有n个点(xi, yi),现在这些点中取若干点构成一个集合S,对它们按照x坐标排序,顺次连接,将会构成一些连续上升、下降的折线,设其数量为f(S)。如下图中,1->2,2->3,3->5,5->6(数字为下图中从左到右的点编号),将折线分为了4部分,每部分连续上升、下降。
现给定k,求满足f(S) = k的S集合个数。
Portal
二维平面上有n个点(xi, yi),现在这些点中取若干点构成一个集合S,对它们按照x坐标排序,顺次连接,将会构成一些连续上升、下降的折线,设其数量为f(S)。如下图中,1->2,2->3,3->5,5->6(数字为下图中从左到右的点编号),将折线分为了4部分,每部分连续上升、下降。
现给定k,求满足f(S) = k的S集合个数。
第一行两个整数n和k,以下n行每行两个数(xi, yi)表示第i个点的坐标。所有点的坐标值都在[1, 100000]内,且不存在两个点,x坐标值相等或y坐标值相等
输出满足要求的方案总数 mod 100007的结果
对于100%的数据,n <= 50000,0 < k <= 10
先按x坐标排序
f[i][j][0/1] 表示前 i 个构成 j 个折线,最后一个折线为上升/下降的方案数。
f[i][j][0]=∑i−1k=1f[k][j][0]+f[k][j−1][1] (y[k]<y[i])
f[i][j][1]=∑i−1k=1f[k][j][1]+f[k][j−1][0] (y[k]>y[i])
用个树状数组维护一下就好了
#include
#include
#include
#define N 50005
#define mod 100007
#define INF 1000000001
using namespace std;
typedef long long ll;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,tot,ans;
int Hash[N],szsz[11][2][N];
int f[N][11][2];
class Point{
public:
int x,y;
}e[N];
bool operator <(Point a,Point b){
return a.xint lowbit(int x){
return x&-x;
}
void Update(int x,int y,int j,int k)
{
while(x<=tot)
{
szsz[j][k][x]=(szsz[j][k][x]+y)%mod;
x+=lowbit(x);
}
}
int Query(int x,int j,int k)
{
int rtn=0;
while(x)
{
rtn=(rtn+szsz[j][k][x])%mod;
x-=lowbit(x);
}
return rtn;
}
void Input_Init()
{
n=read(),m=read();
for(int i=1;i<=n;i++) e[i].x=read(),e[i].y=Hash[i]=read();
sort(e+1,e+1+n);
sort(Hash+1,Hash+1+n);
tot=unique(Hash+1,Hash+1+n)-Hash-1;
}
int Find(int x)
{
int l=1,r=tot,rtn;
while(l<=r)
{
int mid=l+r>>1;
if(Hash[mid]>=x) rtn=mid,r=mid-1;
else l=mid+1;
}
return rtn;
}
void DP()
{
for(int i=1;i<=n;i++)
{
static int tx;
tx=Find(e[i].y);f[i][0][0]=f[i][0][1]=1;
Update(tx,1,0,0);Update(tx,1,0,1);
for(int j=1;j<=m;j++)
{
f[i][j][0]+=Query(tx-1,j,0)+Query(tx-1,j-1,1);
f[i][j][1]+=Query(tot,j,1)-Query(tx,j,1)+Query(tot,j-1,0)-Query(tx,j-1,0);
f[i][j][0]%=mod;f[i][j][1]%=mod;
if(f[i][j][1]<0) f[i][j][1]+=mod;
Update(tx,f[i][j][0],j,0);Update(tx,f[i][j][1],j,1);
}
}
for(int i=1;i<=n;i++)
{
ans+=f[i][m][0];if(ans>=mod) ans-=mod;
ans+=f[i][m][1];if(ans>=mod) ans-=mod;
}
printf("%d\n",ans);
}
int main()
{
Input_Init();
DP();
return 0;
}