BZOJ3688: 折线统计

来源:互联网 发布:mac 照片浏览工具 编辑:程序博客网 时间:2024/06/06 09:09

Portal

3688: 折线统计

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

二维平面上有n个点(xi, yi),现在这些点中取若干点构成一个集合S,对它们按照x坐标排序,顺次连接,将会构成一些连续上升、下降的折线,设其数量为f(S)。如下图中,1->2,2->3,3->5,5->6(数字为下图中从左到右的点编号),将折线分为了4部分,每部分连续上升、下降。

 

现给定k,求满足f(S) = k的S集合个数。


Input

第一行两个整数n和k,以下n行每行两个数(xi, yi)表示第i个点的坐标。所有点的坐标值都在[1, 100000]内,且不存在两个点,x坐标值相等或y坐标值相等

Output

输出满足要求的方案总数 mod 100007的结果

Sample Input


5 1

5 5

3 2

4 4

2 3

1 1

Sample Output


19



HINT


对于100%的数据,n <= 50000,0 < k <= 10

先按x坐标排序
f[i][j][0/1]表示前i个构成j个折线,最后一个折线为上升/下降的方案数。
f[i][j][0]=i1k=1f[k][j][0]+f[k][j1][1]   (y[k]<y[i])
f[i][j][1]=i1k=1f[k][j][1]+f[k][j1][0]   (y[k]>y[i])

用个树状数组维护一下就好了

【代码】

#include <iostream>#include <cstdio>#include <algorithm>#define N 50005#define mod 100007#define INF 1000000001using 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.x<b.x;}int 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;}
0 0