zoukankan      html  css  js  c++  java
  • 动态规划+树状数组优化 BZOJ3688 折线统计

    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
    ",ans);
    43     return 0;
    44 }
  • 相关阅读:
    Git常用命令
    C++ 四种强制类型转换
    Linux系统日志及日志分析
    C/C++中的getline函数总结:
    标准C++中的string类的用法总结
    C++中map的基本操作和使用;
    一个C++类的注释:
    C++ 中宏的使用 --来自:http://blog.csdn.net/hgl868/article/details/7058906
    c++ 的vector
    c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast
  • 原文地址:https://www.cnblogs.com/zwube/p/7077595.html
Copyright © 2011-2022 走看看