ACM-线段树区间更新+离散化
区间更新与单点更新最大的不同就在于Lazy思想:
http://blog.sina.com.cn/s/blog_a2dce6b30101l8bi.html
可以看这篇文章,讲得比较清楚
在具体使用上,因为是成段更新,目标区间内所有区间都需要更新,所以update时可以专门去找区间,不用一个个找点。所以可以不用node保存每个点左右范围,用a[]保存值,col[]保存标记反而比较方便
区间替换和区间增减在我的http://www.cnblogs.com/qlky/p/5690265.html中都写了,这里讲一下离散化:
离散化就是有时n个点的数据范围过大,或者过于分散。我们将节点映射到1-n中可以简化问题。基本过程如下:
- 记录每个点的左端和右端,全部保存到一个数组a中并排序
- 节点去重
- 如果两个节点间距离大于1,添加一个中间节点
- 再次对a排序
- 在a中二分搜索原来每个点的左右端,将索引值保存在线段树中
示例代码:
sf("%d",&n);
int cnt = ,len = ;
for(i=;i<=n;i++)//记录头尾
{
sf("%d %d",&s1[i],&s2[i]);
a[++cnt] = s1[i];
a[++cnt] = s2[i];
}
sort(a+,a++cnt); for(i=;i<=cnt;i++)//去重
{
if(a[i]!=a[i-]) a[++len] = a[i];
} for(i=len;i>;i--)//添加中间值
{
if(a[i]-a[i-]>) a[++len] = a[i]-;
}
sort(a+,a++len); for(i=;i<=n;i++)
{
int l = BSearch(,len,s1[i]);
int r = BSearch(,len,s2[i]);
update(i,l,r,,len,);
}
以poj 2528为例:
http://blog.csdn.net/non_cease/article/details/7383736
题意:n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。
求出最后还能看见多少张海报。
输入:
1
5
1 4
2 6
8 10
3 4
7 10
解法:离散化,如下面的例子(题目的样例),因为单位1是一个单位长度,将下面的
1 2 3 4 6 7 8 10
— — — — — — — —
1 2 3 4 5 6 7 8
离散化 X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] = 8; X[8] = 10
于是将一个很大的区间映射到一个较小的区间之中了,然后再对每一张海报依次更新在宽度为1~8的墙上(用线段树),最后统计不同颜色的段数。
但是只是这样简单的离散化是错误的,
如三张海报为:1~10 1~4 6~10
离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。
新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)
X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10
这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3
最终,1~2为2,3为1,4~5为3,于是输出正确结果3。
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std; #define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 10000 + 5
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f int n,m; int a[MAXN<<],col[MAXN<<],ans; int s1[MAXN],s2[MAXN]; bool hh[MAXN]; void PushDown(int rt)
{
if(col[rt] != -)
{
col[rt<<] = col[rt<<|] = col[rt];
col[rt] = -;
}
} void update(int val,int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R)
{
col[rt] = val;
return;
}
PushDown(rt);
int mid = (l + r)>>;
if (L <= mid)
{
update(val,L,R,l,mid,rt<<);
}
if(R > mid)
{
update(val,L,R,mid+,r,rt<<|);
}
} void query(int l,int r,int rt)
{
if(l==r)
{
if(!hh[col[rt]])
{
ans++;
hh[col[rt]] = true;
}
return;
}
PushDown(rt);
int mid = (l + r)>>;
query(l,mid,rt<<);
query(mid+,r,rt<<|);
} int BSearch(int lo, int hi, int v)
{
int mid;
while (lo <= hi)
{
mid = (lo + hi) >> ;
if (a[mid] == v) return mid;
else if (a[mid] > v) hi = mid - ;
else lo = mid + ;
}
return -;
} int main()
{
int t,i,kase=;
sf("%d",&t);
while(t--)
{
mem(col,-);
mem(a,);
mem(hh,false);
sf("%d",&n);
int cnt = ,len = ;
for(i=;i<=n;i++)//????
{
sf("%d %d",&s1[i],&s2[i]);
a[++cnt] = s1[i];
a[++cnt] = s2[i];
}
sort(a+,a++cnt); for(i=;i<=cnt;i++)//??
{
if(a[i]!=a[i-]) a[++len] = a[i];
} for(i=len;i>;i--)//?????
{
if(a[i]-a[i-]>) a[++len] = a[i]-;
}
sort(a+,a++len); for(i=;i<=n;i++)
{
int l = BSearch(,len,s1[i]);
int r = BSearch(,len,s2[i]);
update(i,l,r,,len,);
}
ans = ;
query(,len,);
pf("%d\n",ans);
}
return ;
}
ACM-线段树区间更新+离散化的更多相关文章
- POJ-2528 Mayor's posters (线段树区间更新+离散化)
题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...
- POJ 2528 Mayor's posters (线段树区间更新+离散化)
题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...
- POJ2528:Mayor's posters(线段树区间更新+离散化)
Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...
- POJ-2528 Mayor's posters(线段树区间更新+离散化)
http://poj.org/problem?id=2528 https://www.luogu.org/problem/UVA10587 Description The citizens of By ...
- POJ2528 Mayor's posters(线段树&区间更新+离散化)题解
题意:给一个区间,表示这个区间贴了一张海报,后贴的会覆盖前面的,问最后能看到几张海报. 思路: 之前就不会离散化,先讲一下离散化:这里离散化的原理是:先把每个端点值都放到一个数组中并除重+排序,我们就 ...
- POJ 2528 Mayor's posters(线段树/区间更新 离散化)
题目链接: 传送门 Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Description The citizens of By ...
- POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)
POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...
- POJ 2528 Mayor's posters 【区间离散化+线段树区间更新&&查询变形】
任意门:http://poj.org/problem?id=2528 Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total S ...
- HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...
- HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...
随机推荐
- tcp连接过程中的三次握手和四次挥手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手握手建立连接 @第一次握手: 建立连接是,客户端A发送SYN包到服务器B,并进入SYN_SEND状态,等待B确认. @第二次握手: 服务 ...
- 也谈ObjectARX多版本批量编译
也谈ObjectARX多版本批量编译 by edata 2017-12-10 因某些原因,我的电脑系统依旧是windows XP,所以能安装的vs最高版本是vs2010,以下均在vs2010上实现,其 ...
- JAVA数据结构--希尔排序
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能.这样可以让一个元素可以一次性地朝最终位置前进一大步.然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需 ...
- Trailing Loves (or L'oeufs?)
The number "zero" is called "love" (or "l'oeuf" to be precise, literal ...
- Jquery动态绑定事件处理函数 bind / on / delegate
1.bind方法绑定的事件处理函数不会应用到后来添加到DOM中的新元素.比如你在用bind给页面元素绑定事件之后,又新添加了一些与之前绑定过事件的元素一样的DOM元素,但是这些事件并不能在新的DOM元 ...
- ZOJ - 2676 01分数规划 浮点ISAP
题意:求最小割集\(C\),使得\(\frac{\sum_{i∈C} cost_i}{|C|}\)最小 模型就是01分数规划\(\frac{\sum_{i=1}^{m}cost_i*x}{\sum_{ ...
- MITK 手册
可怜这么有用的开源竟然没有中文手册, MITK Plugin Manuals Overview The Basic Image Processing Plugin The DataManager ...
- webgoat环境搭建
链接: https://pan.baidu.com/s/1gfEKIyB 密码: 5zdq 1:配置Java环境变量,过程请找度娘 2:解压下载好的tomcat 3:将webgoat-containe ...
- Centos 添加swap
swap是linux系统的虚拟内存,物理内存不足时,会用到.生产环境,最好添加上,以防内存异常暴增时,系统出现问题. 查看系统是否有swap分区,执行如下命令,若Swap那一行都为0,则表示没有Swa ...
- Oracle ASM 常用命令
01, 查看磁盘路径 select name,path,group_number from v$asm_disk_stat; 02, 查看磁盘组信息 select state,name,type,to ...