• hdu -4325-Flowers(离散化 线段树)


    http://acm.hdu.edu.cn/showproblem.php?pid=4325

    题目意思:

    给你N个花开的时间段,然后在有M个时间点,问你在这个时间点有多少花开着。

    昨天刚做的一个类似的题,用线段树加离散化,然后赶紧敲,然后错八次。

    最后还是没做出来。

    那么思路还是线段树加离散化。

    题目给的每个花开花谢的范围很大,但花的数目只有1e5,很容易就想到了离散化,然后就是用线段树去处理,找每个花开的段,最后lazy下放到

    每个时间点,这样就知道每个时间点开的花数。

    这题大致思路是这样的,但你会发现M次查询时,有的时间点,你在离散化时,你没将它加入,所以你在离散化后的数组里找不到这个点。当时没想到将询问的点加入一起离散化,然后各种二分,然并ruan.

    下面给出代码:

      1 /*sjy*/
      2 #include<stdio.h>
      3 #include<algorithm>
      4 #include<stdlib.h>
      5 #include<string.h>
      6 #include<iostream>
      7 #include<math.h>
      8 void add(int l,int r,int k,int aa,int dd);
      9 int kr(int n,int m,int t);
     10 void lazy(int l,int r,int k);
     11 int  findd(int l,int r,int k,int aa,int dd);
     12 int cmp(const void*p,const void*q);
     13 /*int er(int n,int m,int t);*/
     14 typedef struct pp
     15 {
     16     int x;
     17     int y;
     18 }ss;
     19 int N,M,V;
     20 int tree[8*100005];//线段树数组
     21 ss a[100005];
     22 ss b[2*100005];
     23 int c[2*100005];
     24 /*int yk[2*100005];*/
     25 int kp[100005];
     26 using namespace std;
     27 int main(void)
     28 {
     29     int n,i,j,k,p,q,x,y,s;
     30     scanf("%d",&n);
     31     for(i=1; i<=n; i++)
     32     {
     33         memset(tree,0,sizeof(tree));
     34         scanf("%d %d",&N,&M);
     35         int cnt=0;
     36         int sum=-1;
     37         for(j=0; j<N; j++)
     38         {
     39             scanf("%d %d",&a[j].x,&a[j].y);
     40             b[cnt].x=a[j].x;
     41             cnt++;
     42             b[cnt].x=a[j].y;
     43             cnt++;
     44             if(sum<a[j].y)
     45             {
     46                 sum=a[j].y;
     47             }
     48         }
     49         for(j=0;j<M;j++)
     50         {
     51             scanf("%d",&kp[j]);
     52             b[cnt++].x=kp[j];
     53         }//询问的点加入离散化
     54         qsort(b,cnt,sizeof(ss),cmp);//排序离散化
     55         int vv=0;
     56         c[vv]=0;
     57         int rr=0;
     58         for(j=1; j<cnt; j++)
     59         {
     60             if(b[j].x!=b[j-1].x)
     61             {
     62                 vv++;
     63                 c[j]=vv;
     64                 rr=0;
     65                 /*yk[j]=rr;*/
     66             }
     67             else
     68             {
     69                 c[j]=vv;
     70                 /*yk[j]=rr;*/
     71             }
     72         }
     73         for(j=0; j<N; j++)
     74         {
     75             x=kr(0,cnt-1,a[j].x);//二分找点
     76             y=kr(0,cnt-1,a[j].y);
     77             add(x,y,0,0,vv);//线段数更新加段
     78         }
     79         lazy(0,vv,0);printf("Case #%d:
    ",i);
     80         for(j=0;j<M;j++)
     81         {
     82             int uu=kr(0,cnt-1,kp[j]);
     83             int yy=findd(uu,uu,0,0,vv);//查询问的时间段因为为点所以l=r
     84             printf("%d
    ",yy);
     85         }
     86 
     87     }
     88     return 0;
     89 
     90 }
     91 void add(int l,int r,int k,int aa,int dd)//线段数更新
     92 {
     93     if(l>dd||r<aa)
     94     {
     95         return ;
     96     }
     97     else if(l<=aa&&r>=dd)
     98     {
     99         tree[k]++;
    100     }
    101     else
    102     {
    103         add(l,r,2*k+1,aa,(aa+dd)/2);
    104         add(l,r,2*k+2,(aa+dd)/2+1,dd);
    105     }
    106 }
    107 
    108 void lazy(int l,int r,int k)//最后下放操作
    109 {
    110     if(l==r)
    111     {
    112         return ;
    113     }
    114     else
    115     {
    116         tree[2*k+1]+=tree[k];
    117         tree[2*k+2]+=tree[k];
    118         lazy(l,(l+r)/2,2*k+1);
    119         lazy((l+r)/2+1,r,2*k+2);
    120     }
    121 }
    122 
    123 
    124 int  findd(int l,int r,int k,int aa,int dd)
    125 {
    126     if(l>dd||r<aa)
    127     {
    128         return 0;
    129     }
    130     else if(l<=aa&&r>=dd)
    131     {
    132         return tree[k];
    133     }
    134     else
    135     {
    136         int nx=findd(l,r,2*k+1,aa,(aa+dd)/2);
    137         int ny=findd(l,r,2*k+2,(aa+dd)/2+1,dd);
    138         return nx+ny;
    139     }
    140 
    141 }
    142 
    143 /*int er(int n,int m,int t)
    144 {
    145     int y=(n+m)/2;
    146     if(b[y].x==t)
    147     {
    148         return c[y];
    149     }
    150     if(m<n)
    151     {
    152         return -1;
    153     }
    154     if(m==n&&b[m].x!=t)
    155     {
    156         return -1;
    157     }
    158 
    159     else if(m-n==1&&b[n].x<=t&&b[m].x>=t)
    160     {
    161         V=yk[n];
    162         return c[n];
    163     }
    164     else if(b[y].x<t)
    165     {
    166         return er(y,m,t);
    167     }
    168     else return er(n,y,t);
    169 
    170 }*/
    171 int kr(int n,int m,int t)//二分找点
    172 {
    173     int yy=(n+m)/2;
    174     if(b[yy].x==t)
    175     {
    176         return c[yy];
    177     }
    178     else if(b[yy].x>t)
    179     {
    180         return kr(n,yy-1,t);
    181     }
    182     else return kr(yy+1,m,t);
    183 }
    184 int cmp(const void*p,const void*q)
    185 {
    186     ss*w=(ss*)p;
    187     ss*ww=(ss*)q;
    188 
    189      return w->x-ww->x;
    190 }
    油!油!you@
  • 相关阅读:
    选择排序法
    计算大阶乘(值很大)
    递归计算阶乘
    计算m的m次方倒数的和
    使用文件(FILE)输入输出
    判断回文数
    最小公倍数(调用函数与全局变量)
    How to 共用体
    How to 枚举
    有效编写软件的75条建议(转)
  • 原文地址:https://www.cnblogs.com/zzuli2sjy/p/4966555.html
Copyright © 2020-2023  润新知