博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ACM-线段树区间更新+离散化
阅读量:4945 次
发布时间:2019-06-11

本文共 3772 字,大约阅读时间需要 12 分钟。

 

区间更新与单点更新最大的不同就在于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 = 0,len = 1;        for(i=1;i<=n;i++)//记录头尾        {            sf("%d %d",&s1[i],&s2[i]);            a[++cnt] = s1[i];            a[++cnt] = s2[i];        }        sort(a+1,a+1+cnt);        for(i=2;i<=cnt;i++)//去重        {            if(a[i]!=a[i-1]) a[++len] = a[i];        }        for(i=len;i>1;i--)//添加中间值        {            if(a[i]-a[i-1]>1) a[++len] = a[i]-1;        }        sort(a+1,a+1+len);        for(i=1;i<=n;i++)        {            int l = BSearch(1,len,s1[i]);            int r = BSearch(1,len,s2[i]);            update(i,l,r,1,len,1);        }

 

以poj 2528为例:

http://blog.csdn.net/non_cease/article/details/7383736

题意:n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。

      求出最后还能看见多少张海报。

输入:

151 42 68 103 47 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 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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 0x3f3f3f3fint n,m;int a[MAXN<<4],col[MAXN<<4],ans;int s1[MAXN],s2[MAXN];bool hh[MAXN];void PushDown(int rt){ if(col[rt] != -1) { col[rt<<1] = col[rt<<1|1] = col[rt]; col[rt] = -1; }}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)>>1; if (L <= mid) { update(val,L,R,l,mid,rt<<1); } if(R > mid) { update(val,L,R,mid+1,r,rt<<1|1); }}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)>>1; query(l,mid,rt<<1); query(mid+1,r,rt<<1|1);}int BSearch(int lo, int hi, int v){ int mid; while (lo <= hi) { mid = (lo + hi) >> 1; if (a[mid] == v) return mid; else if (a[mid] > v) hi = mid - 1; else lo = mid + 1; } return -1;}int main(){ int t,i,kase=1; sf("%d",&t); while(t--) { mem(col,-1); mem(a,0); mem(hh,false); sf("%d",&n); int cnt = 0,len = 1; for(i=1;i<=n;i++)//???? { sf("%d %d",&s1[i],&s2[i]); a[++cnt] = s1[i]; a[++cnt] = s2[i]; } sort(a+1,a+1+cnt); for(i=2;i<=cnt;i++)//?? { if(a[i]!=a[i-1]) a[++len] = a[i]; } for(i=len;i>1;i--)//????? { if(a[i]-a[i-1]>1) a[++len] = a[i]-1; } sort(a+1,a+1+len); for(i=1;i<=n;i++) { int l = BSearch(1,len,s1[i]); int r = BSearch(1,len,s2[i]); update(i,l,r,1,len,1); } ans = 0; query(1,len,1); pf("%d\n",ans); } return 0;}

 

转载于:https://www.cnblogs.com/qlky/p/5716796.html

你可能感兴趣的文章
sqlserver中如何将mdf文件还原到数据库
查看>>
getResponseHeader常见返回值
查看>>
【LOJ6052】「雅礼集训 2017 Day11」DIV(杜教筛)
查看>>
驱动-字符设备驱动程序开发(第二天)
查看>>
PHP时间戳与日期的相互转换
查看>>
设计模式(十一): 模板模式
查看>>
Bit、Byte、kb、KB、MB、KiB、MiB各表示什么意思?
查看>>
SVN强制注释
查看>>
SmartFoxServer学习(3)--第一个Extension
查看>>
bzoj3622: 已经没有什么好害怕的了
查看>>
bzoj3957: [WF2011]To Add or to Multiply
查看>>
在Openstack中使用Ubuntu的Cloud images如何设置密码
查看>>
Oracle中的索引详解
查看>>
git-合并子树
查看>>
关于JS浅拷贝和深拷贝
查看>>
Hadoop点滴-外围概念
查看>>
Nginx相关介绍
查看>>
Delphi中建议使用的语句
查看>>
旅行家的预算 1999年NOIP全国联赛普及组NOIP全国联赛提高组
查看>>
最长严格上升子序列
查看>>