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:\n",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\n",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 }
时间: 2024-10-12 17:05:58

hdu -4325-Flowers(离散化 线段树)的相关文章

HDOJ 题目4325 Flowers(线段树+离散化)

Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2493    Accepted Submission(s): 1235 Problem Description As is known to all, the blooming time and duration varies between different kind

离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers

题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前花开的数量,放张图易理解: 还有一种做法用尺取法的思想,对暴力方法优化,对询问点排序后再扫描一遍,花开+1,花谢-1.详细看代码. 收获:一题收获很多:1. 降低复杂度可以用二分 2. 线段计数问题可以在端点标记1和-1 3. 离散化+线段树 终于会了:) (听说数据很水?) 代码1:离散化+线段树

[HDU 6447][YJJ&#39;s Salesman][2018CCPC网络选拔赛 1010][离散化+线段树+DP]

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6447 题意: 左上角(0,0),右下角(10^9,10^9)的网格,其中有n(1<=n<=10^5)个方格内有权值. 一次只能沿右,下,右下三个方向走一个格子,只有沿右下方向走到格子里才可以获得权值. 问从(0,0)到(10^9,10^9)的路径最大权值是多少. 思路: 网格路径权值问题,第一感考虑DP,x从上往下,y从左往右刷表,状态转移方程为dp[i][j]=max(dp[i-1][j],dp[

HDU 4902 Nice boat(线段树)

HDU Nice boat 题目链接 题意:给定一个序列,两种操作,把一段变成x,把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 思路:线段树,每个结点多一个cover表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1

hdu 2795 Billboard(线段树)

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10890    Accepted Submission(s): 4827 Problem Description At the entrance to the university, there is a huge rectangular billboard of

poj 2528 Mayor&#39;s posters【离散化+线段树】

题目:poj 2528 Mayor's posters 题意:给一个长度非常长的墙上贴长度为ai的海报,由于有的会覆盖掉,求最后能看见的海报个数. 分析:题目和POJ2777 一模一样,方法也一样,只不过这个要离散化,其次要数组开大一点.至少2倍. 离散化的时候用了C++的 pair 类,还是比较好用的. 代码: #include <iostream> #include <algorithm> #include <utility> #include <cstrin

hdu 3016 Man Down (线段树 + dp)

题目大意: 是男人就下一般层...没什么可以多说的吧. 注意只能垂直下落. 思路分析: 后面求最大值的过程很容易想到是一个dp的过程 . 因为每一个plane 都只能从左边 从右边下两种状态. 然后我们所需要处理的问题就是 ,你如何能快速知道往左边下到哪里,往右边下到哪里. 这就是线段树的预处理. 讲线段按照高度排序. 然后按照高度从小到大加入到树中. 然后去寻找左端点 和 右端点最近覆盖的线段的编号. #include <cstdio> #include <iostream> #

POJ 2299 离散化线段树

点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 40827   Accepted: 14752 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by

南阳理工 题目9:posters(离散化+线段树)

posters 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally deci

Mayor&#39;s posters(离散化线段树)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 54067   Accepted: 15713 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post