动态规划 BZOJ3688 折线统计

来源:互联网 发布:ae软件怎么用 编辑:程序博客网 时间:2024/06/09 17:36

3688: 折线统计

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 234  Solved: 118
[Submit][Status][Discuss]

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

 

Source

 

显然是要先按x坐标排序,这不是废话吗2333……y坐标也可以离散了在做,不过没必要

f[i][j][0]/[1]表示前i个点中,选择j段,最后一段为上升/下降的方案数

f[i][j][0]=∑(f[ii][j][0]+f[ii][j-1][1]) (ii<i且node[i].y<node[ii].y)

另一个同理

 

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,k,ans; 7 struct data{ 8     int x,y; 9 }node[100010];10 int f[100010][15][2],t[100010][15][2];11 bool cmp(const data&aa,const data&bb){12     return aa.x<bb.x;13 }14 void add(int pos,int kk,int tt,int val){15     for(int i=pos;i<=100000;i+=i&(-i)) t[i][kk][tt]=(t[i][kk][tt]+val)%100007;16 }17 int ask(int pos,int kk,int tt){18     int rt=0;19     for(int i=pos;i;i-=i&(-i)) rt=(rt+t[i][kk][tt])%100007;20     return rt;21 }22 int main(){23     scanf("%d%d",&n,&k);24     for(int i=1;i<=n;i++) scanf("%d%d",&node[i].x,&node[i].y);25     sort(node+1,node+n+1,cmp);26     for(int i=1;i<=n;i++){27         f[i][0][0]=f[i][0][1]=1;28         add(node[i].y,0,0,1);29         add(node[i].y,0,1,1);30         for(int kk=1;kk<=k;kk++){31             f[i][kk][0]=(f[i][kk][0]+ask(node[i].y-1,kk,0)+ask(node[i].y-1,kk-1,1))%100007;32             f[i][kk][1]=(f[i][kk][1]+ask(100000,kk,1)-ask(node[i].y,kk,1)+ask(100000,kk-1,0)-ask(node[i].y,kk-1,0))%100007;33             if(f[i][kk][1]<0) f[i][kk][1]+=100007;//!!!34             add(node[i].y,kk,0,f[i][kk][0]);35             add(node[i].y,kk,1,f[i][kk][1]);36         }37     }38     for(int i=1;i<=n;i++){39         ans=(ans+f[i][k][0])%100007;40         ans=(ans+f[i][k][1])%100007;41     }42     printf("%d\n",ans);43     return 0;44 }