zoukankan      html  css  js  c++  java
  • BZOJ3688折线统计 dp+线段树

    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

    题解:

      三维dp,dp[i][j][0]表示i个点,j个折线,最后状态为上升,dp[i][j][1]表示i个点,j个折线,最后状态为下降。用线段树或树状数组维护前缀和优化logn。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cmath>
     5 using namespace std;
     6 const int MAXN=100001;
     7 const int mod=100007;
     8 struct Point
     9 {
    10     int x,y;
    11 }p[MAXN];
    12 bool cmp(Point x,Point y)
    13 {
    14     return  x.x<y.x;
    15 }
    16 int dp[MAXN][11][2],pre[MAXN][11][2];
    17 int lowbit(int x) 
    18 {
    19     return (x&(-x));
    20 }
    21 void add(int x,int y,int k,int tar)
    22 {
    23     int i;
    24     for(i=x;i<MAXN;i+=lowbit(i))
    25     pre[i][y][k]=(pre[i][y][k]+tar)%mod;
    26 }
    27 int Query(int x,int y,int k)
    28 {
    29     int ans=0,i;
    30     for(i=x;i;i-=lowbit(i))
    31     ans=(ans+pre[i][y][k])%mod;
    32     return ans;
    33 }
    34 int main(int argc, char *argv[])
    35 {
    36     int n,m,i,j,k,tot=0;
    37     scanf("%d%d",&n,&k);
    38     for(i=1;i<=n;i++)
    39     scanf("%d%d",&p[i].x,&p[i].y);
    40     sort(p+1,p+n+1,cmp);
    41     for(i=1;i<=n;i++)
    42     {
    43         dp[i][0][0]=dp[i][0][1]=1;
    44         add(p[i].y,0,0,1),add(p[i].y,0,1,1);
    45         for(j=1;j<=k;j++) {
    46             dp[i][j][0]=(dp[i][j][0]+Query(p[i].y-1,j,0)+Query(p[i].y-1,j-1,1))%mod;
    47             dp[i][j][1]=(dp[i][j][1]+Query(MAXN-1,j,1)-Query(p[i].y,j,1)+Query(MAXN-1,j-1,0)-Query(p[i].y,j-1,0))%mod;
    48             if(dp[i][j][1]<0) dp[i][j][1]+=mod;
    49             add(p[i].y,j,0,dp[i][j][0]);
    50             add(p[i].y,j,1,dp[i][j][1]);
    51         }
    52     }
    53     for(i=1;i<=n;i++) tot=(tot+dp[i][k][0])%mod,tot=(tot+dp[i][k][1])%mod;
    54     printf("%d
    ",tot%mod);
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    struct pack unpack
    读书笔记 第四章&第五章
    The Sieve of Eratosthens(爱拉托逊斯筛选法)
    2013年3月百度之星A题
    2013年3月百度之星B题
    好句子
    BFS 与 DFS
    记录本
    HDU 2028 如何计算最小公倍数?
    HDU 2015 偶数求和 解题报告
  • 原文地址:https://www.cnblogs.com/BeyondW/p/5773217.html
Copyright © 2011-2022 走看看