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
  • 相关阅读:
    Bit Manipulation
    218. The Skyline Problem
    Template : Two Pointers & Hash -> String process
    239. Sliding Window Maximum
    159. Longest Substring with At Most Two Distinct Characters
    3. Longest Substring Without Repeating Characters
    137. Single Number II
    142. Linked List Cycle II
    41. First Missing Positive
    260. Single Number III
  • 原文地址:https://www.cnblogs.com/BeyondW/p/5773217.html
Copyright © 2011-2022 走看看