线段树或树状数组---Flowers
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=4325
Description
Input
For each case, the first line contains two integer N and M, where N (1 <= N <= 10^5) is the number of flowers, and M (1 <= M <= 10^5) is the query times.
In the next N lines, each line contains two integer S i and T i (1 <= S i <= T i <= 10^9), means i-th flower will be blooming at time [S i, Ti].
In the next M lines, each line contains an integer T i, means the time of i-th query.
Output
Sample outputs are available for more details.
Sample Input
1 1
5 10
4
2 3
1 4
4 8
1
4
6
Sample Output
题意:有n种花,给了这n种花的花期时间,Si~Ti,求在某一时间t,有多少种花正在开放。
思路:这题给的花期时间数据为1~10^9,无法开辟这么大的数组,不能直接建树,必须先将数据进行离散化。离散化:在百科上看到一句很好的话:“离散化就是把连续的量,变成离散的量即变成一个一个的值”,例如区间(1,100)由于这是一个实数区间,其中间的值有无数个,如果我们能把它变为1到100内的整数,这样这些数就变成了有限个,即离散了; ,我们将每个区间的端点都存到一个数组中,然后将这些端点,按照从小到大排列(之后要去除这个数组中重复的点),并建立为与其下标的映射,然后用其下标建树,因为我们只是使用了需要的空间,并没有在整个空间上建树,这样就大大节省了空间和时间,如题中第二个例子,我们将所有数据按照从小到大排列后为1 2 3 4 6 8 分别对应下标1 2 3 4 5 6,此题数据小我们看不出明显的差别,但是如果数据中有区间(1000,10000),那差别马上就出来了,比如我们把题中的区间(4,8)换做(1000,10000)那么如果采用离散化思想,我们还是先排列大小 1 2 3 6 1000 10000对应下标1 2 3 4 5 6,我们只需建一棵根为6的树即可,如果不用离散化,我们就需要建造根为10000的树,大大浪费了空间。
然而!!!我发现同学他们的代码没有使用离散化,而是开辟了150000的空间就过了,很明显测试数据没有很大,都在150000以内,唉!所以可以不用离散化。
方法一:使用树状数组,若花期为t1~t2,更新t1-1及t1-1以下的子树根节点都减一,更新t2及t2以下的子树根节点加一,若求x时刻有多少种花正开着,将x及上方一路节点均相加,最后的和即是结果。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define N 152005
using namespace std;
int c[N]; int Lowbit(int t)
{ ///设k为t末尾0的个数,则求得为2^k=t&(t^(t-1));
return t&(t^(t-));
}
void update(int x,int t)
{
while(x > )
{
c[x]+=t;
x -= Lowbit(x);
}
}
int sum(int li)
{
int sum=;
while(li<=N)
{
sum+=c[li];
li=li+Lowbit(li);
}
return sum;
} int main()
{
int T;
int n,M,t1,t2,x,Case=;
scanf("%d",&T);
while(T--)
{
memset(c,,sizeof(c));
scanf("%d%d",&n,&M);
while(n--)
{
scanf("%d%d",&t1,&t2);
update(t1-,-);
update(t2,);
}
printf("Case #%d:\n",Case++);
while(M--)
{
scanf("%d",&x);
printf("%d\n",sum(x));
}
}
return ;
}
方法二:使用线段树进行区间更新。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int Max=;
int N,M;
int c[Max]; struct Node
{
int l,r;
int cnt;
}node[*Max]; void build(int L,int R,int i)
{
node[i].l=L;
node[i].r=R;
node[i].cnt=;
if(L==R) return;
int mid=(L+R)/;
build(L,mid,*i);
build(mid+,R,*i+);
} int update(int t1,int t2,int i)
{
if(node[i].l==t1&&node[i].r==t2)
{
node[i].cnt++;
return ;
}
int mid=(node[i].l+node[i].r)/;
if(t2<=mid) update(t1,t2,*i);
else if(t1>mid) update(t1,t2,*i+);
else
{
update(t1,mid,*i);
update(mid+,t2,*i+);
}
} int chazhao(int x,int i)
{
int sum=;
if(node[i].l<=x&&node[i].r>=x)
sum+=node[i].cnt;
if(node[i].l>x) return ;
if(node[i].r<x) return ;
sum+=chazhao(x,*i);
sum+=chazhao(x,*i+);
return sum;
} int main()
{
int T,t1,t2,Case=;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
build(,Max,);
for(int i=;i<=N;i++)
{
scanf("%d%d",&t1,&t2);
update(t1,t2,);
}
for(int i=;i<M;i++)
scanf("%d",&c[i]);
printf("Case #%d:\n",Case++);
for(int i=;i<M;i++)
{
printf("%d\n",chazhao(c[i],));
}
}
return ;
}
线段树或树状数组---Flowers的更多相关文章
- BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P ...
- 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治
LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- HDU 1556 线段树或树状数组,插段求点
1.HDU 1556 Color the ball 区间更新,单点查询 2.题意:n个气球,每次给(a,b)区间的气球涂一次色,问最后每个气球各涂了几次. (1)树状数组 总结:树状数组是一个查 ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS Memory Limit: 32768 K Description The inve ...
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
- Turing Tree_线段树&树状数组
Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems abou ...
随机推荐
- Linux多线程编程(不限Linux)【转】
——本文一个例子展开,介绍Linux下面线程的操作.多线程的同步和互斥. 前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步 ...
- U3D4.X版本无法安装MONODEV编辑器
可能是由于机器无法成功安装.NET 4.0的缘故
- ux.plugin.ConTpl 模版元素监听扩展
/* *tpl模版加入按钮 *<div class="x-button-normal x-button x-iconalign-center x-layout-box-item x-s ...
- 译:在ASP.NET中如何对cookies进行加密和解密
译文地址:http://www.codeproject.com/Tips/872826/Encrypt-Decrypt-Cookies-in-ASP-NET 源代码:http://files.cnbl ...
- 解决git中文乱码
和linux平台一样,在默认设置下,文件名称中包含中文的文件,在工作区状态输出.查看历史更改概要,以及在补丁文件中,文件名中的中文不能正确的显示,而是用若干八进制字符编码来显示,如下: git sta ...
- Fireasy新版本发布
1.5.40.42028 2015-2-4 ** Fireasy.Common 1.DynamicBuilder新增使用表达式SetCustomAttribute的重载方法 2.DateTimeEx ...
- 如何对excel进行列查重
学习了excel函数:countif.表达式:COUNTIF(数据区域,条件),作用:对数据区域内符合条件单元格计数 具体应用 在“姓名”(列A)后插入一列(列B),在B2单元格输入公式“=IF(CO ...
- ruby -- 问题解决(八)解决Paperclip::NotIdentifiedByImageMagickError
好吧!又见 Paperclip::NotIdentifiedByImageMagickError,之前遇过一次... 最近又遇到一次,解决了之后,忘了写博客,然后再次遇到的时候,有一种被车撞到的节奏. ...
- 当他们也换成了Linux OS
近期,斯诺登的事闹得沸沸扬扬,美帝损失了公信.又有传言说Win8给美帝安全局留了后门?XP依旧是生命力旺盛. 还不就是因为那点事儿,看不到人家的源代码? 斗胆提一个问题,如果公务员们或者是一部分,开始 ...
- Outlook Web App简介
一.什么是Outlook Web AppOutlook Web Access简称OWA是基于微软Hosted Exchange技术的托管邮局的一项Web访问功能.通过访问Outlook Web Acc ...