HDU  1698

链接:  http://acm.hdu.edu.cn/showproblem.php?pid=1698

线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)

<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=100001;
int sum[maxn<<2];
int col[maxn<<2];
void pushUP(int rt) //当前节点信息更新给父节点
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int m) //当前节点信息更新给儿子节点
{
if(col[rt])
{
col[rt<<1]=col[rt<<1|1]=col[rt];
sum[rt<<1]=(m-(m>>1))*col[rt];
sum[rt<<1|1]=(m>>1)*col[rt];
col[rt]=0;
}
}
void build(int l,int r,int rt) //建立线段树
{
col[rt]=0;
sum[rt]=1;
if(l==r)
return;
int m=(l+r)/2;
build(lson);
build(rson);
pushUP(rt);
}
void update(int L,int R,int c,int l,int r,int rt) //成段替换,由于只query一次总区间,所以可以直接输出1节点的信息
{
if(L<=l&&r<=R)
{
col[rt]=c;
sum[rt]=(r-l+1)*c;
return;
}
pushdown(rt,r-l+1);
int m=(l+r)/2;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
pushUP(rt);
}
int main()
{
int T,n,m;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
scanf("%d%d",&n,&m);
build(1,n,1);;
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,n,1);
}
printf("Case %d: The total value of the hook is %d.\n",cas , sum[1]);
}
return 0;
}</span>

poj 3468

链接:http://poj.org/problem?id=3468

题解:很好的一个区间更新的线段树的模型,线段树的功能,update成段增减,query区间求和,关键在于对pushdown的理解,当扩展区间与节点上区间完全吻合时,停止向下

#include<iostream>
#include<cstdio>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=100001;
long long sum[maxn<<2],col[maxn<<2];
void pushUP(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int m)
{
if(col[rt])
{
col[rt<<1]+=col[rt];
col[rt<<1|1]+=col[rt];
sum[rt<<1]+=(m-(m>>1))*col[rt];
sum[rt<<1|1]+=(m>>1)*col[rt];
col[rt]=0;
}
}
void build(int l,int r,int rt)
{
col[rt]=0;
if(l==r)
{
scanf("%lld",&sum[rt]);
return;
}
int m=(l+r)/2;
build(lson);
build(rson);
pushUP(rt);
}
void update(int L,int R,int c,int l,int r,int rt) //成段增减
{
if(L<=l&&r<=R)
{
col[rt]+=c;
sum[rt]+=c*(r-l+1);
return;
}
pushdown(rt,r-l+1);
int m=(l+r)/2;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
pushUP(rt);
}
long long query(int L,int R,int l,int r,int rt) //区间求和
{
if(L<=l&&r<=R)
return sum[rt];
pushdown(rt,r-l+1);
long long ret=0;
int m=(l+r)/2;
if(L<=m) ret+=query(L,R,lson);
if(R>m) ret+=query(L,R,rson);
return ret;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--)
{
int a,b,c;
char op[2];
scanf("%s",op);
if(op[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(a,b,1,n,1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,n,1);
}
}
return 0;
}

poj2528(线段树+离散化)

题目链接:http://poj.org/problem?id=2528

题目解答:

离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:

有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。

现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9

然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9

对其升序排序,得2 3 4 6 8 9 10

然后建立映射

2     3     4     6     8     9   10

↓     ↓      ↓     ↓     ↓     ↓     ↓

1     2     3     4     5     6     7

那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。

离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。

由于此题数据较大,所以此题要用离散化

线段树功能:update:成段替换 query:简单hash

#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 11111;
bool hash[maxn];
int li[maxn] , ri[maxn];
int X[maxn*3];
int col[maxn<<4];
int cnt;
void PushDown(int rt) //更新到儿子节点(此处为覆盖,所以用这种方法更新)
{
if (col[rt] != -1)
{
col[rt<<1] = col[rt<<1|1] = col[rt];
col[rt] = -1;
}
}
void update(int L,int R,int c,int l,int r,int rt) //成段替换
{
if (L <= l && r <= R) {
col[rt] = c;
return ;
}
PushDown(rt);
int m = (l + r) >> 1;
if (L <= m) update(L , R , c , lson);
if (m < R) update(L , R , c , rson);
}
void query(int l,int r,int rt) //简单的hash,cnt统计离散化以后的长度
{
if (col[rt] != -1)
{
if (!hash[col[rt]]) cnt ++;
hash[ col[rt] ] = true;
return ;
}
if (l == r) return ;
int m = (l + r) >> 1;
query(lson);
query(rson);
}
int Bin(int key,int n,int X[]) //二分查找的过程
{
int l = 0 , r = n - 1;
while (l <= r)
{
int m = (l + r) >> 1;
if (X[m] == key) return m;
if (X[m] < key) l = m + 1;
else r = m - 1;
}
return -1;
}
int main()
{
int T , n;
scanf("%d",&T);
while (T --)
{
scanf("%d",&n);
int nn = 0;
for (int i = 0 ; i < n ; i ++) //离散化的过程
{
scanf("%d%d",&li[i] , &ri[i]);
X[nn++] = li[i];
X[nn++] = ri[i];
}
sort(X , X + nn);
int m = 1;
for (int i = 1 ; i < nn; i ++)
{
if (X[i] != X[i-1]) X[m ++] = X[i];
}
for (int i = m - 1 ; i > 0 ; i --)
{
if (X[i] != X[i-1] + 1) X[m ++] = X[i-1] + 1;
}
sort(X , X + m);
memset(col , -1 , sizeof(col));
for (int i = 0 ; i < n ; i ++)
{
int l = Bin(li[i], m, X);
int r = Bin(ri[i], m, X);
update(l, r, i, 0, m - 1, 1);
}
cnt = 0;
memset(hash, false, sizeof(hash));
query(0, m - 1, 1);
printf("%d\n",cnt);
}
return 0;
}

线段树之成段更新( 需要用到延迟标记,简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候)的更多相关文章

  1. Codeforces295A - Greg and Array(线段树的成段更新)

    题目大意 给定一个序列a[1],a[2]--a[n] 接下来给出m种操作,每种操作是以下形式的: l r d 表示把区间[l,r]内的每一个数都加上一个值d 之后有k个操作,每个操作是以下形式的: x ...

  2. hdu 1698 Just a Hook(线段树之 成段更新)

    Just a Hook                                                                             Time Limit: ...

  3. hdu 4614 Vases and Flowers(线段树:成段更新)

    线段树裸题.自己写复杂了,准确说是没想清楚就敲了. 先是建点为已插花之和,其实和未插花是一个道理,可是开始是小绕,后来滚雪球了,跪了. 重新建图,分解询问1为:找出真正插画的开始点和终止点,做成段更新 ...

  4. POJ 2777 Count Color(线段树之成段更新)

    Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33311 Accepted: 10058 Descrip ...

  5. POJ3648 A Simple Problem with Integers(线段树之成段更新。入门题)

    A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53169 Acc ...

  6. hdu1698 Just a Hook 线段树:成段替换,总区间求和

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem ...

  7. hdu 1698 线段树(成段替换 区间求和)

    一条钩子由许多小钩子组成 更新一段小钩子 变成铜银金 价值分别变成1 2 3 输出最后的总价值 Sample Input11021 5 25 9 3 Sample OutputCase 1: The ...

  8. POJ 3468 A Simple Problem with Integers //线段树的成段更新

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59046   ...

  9. poj2528 Mayor's posters(线段树之成段更新)

    Mayor's posters Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 37346Accepted: 10864 Descr ...

随机推荐

  1. 74.Search in a 2D Matrix

    /* * 74.Search in a 2D Matrix * 12.5 by Mingyang * 这里面的对应挺巧的: * 这个就是将2D矩阵转化成1行数组的对应表.所以对于二分查找法的初始值为: ...

  2. amplab

    https://github.com/amplab/SparkNet https://amplab.cs.berkeley.edu/

  3. CSS - 如何实现强制不换行、自动换行、强制换行

    来源:http://www.cnblogs.com/mcat/p/4884644.html 强制不换行 div{ white-space:nowrap; } 自动换行 div{ word-wrap: ...

  4. centos安装python的虚拟环境和虚拟管理环境

    一.大部分介绍的方式是使用pip安装:1.pip install virtualenv     2.pip install virtualenvwrapper 但是我安装完,并没有相应的命令:virt ...

  5. HDU - 4630 No Pain No Game (线段树 + 离线处理)

    id=45786" style="color:blue; text-decoration:none">HDU - 4630 id=45786" style ...

  6. ubuntu compile php from source code

    10down vote Assuming that you already have the OpenSSL libraries and header files (on rpm systems th ...

  7. flex 操作xml 实现增删改查 .

    一 在介绍Flex中操作XML之前,首先简单介绍下XML中的基本术语. 元素:XML中拥有开始标签和结束标签的这一块称为“元素”    节点:把XML元素与文本结合起来统称为节点    根节点:位于整 ...

  8. 【转载】关于C#静态构造函数的几点说明

    一.定义 静态构造函数是C#的一个新特性,其实好像很少用到.不过当我们想初始化一些静态变量的时候就需要用到它了.这个构造函数是属于类的,而不是属于哪里实例的,就是说这个构造函数只会被执行一次.也就是在 ...

  9. js 监控浏览器关闭(完美兼容chrome & ie & fire fox)

    var UnloadConfirm = {}; UnloadConfirm.MSG_UNLOAD = "数据尚未保存,离开后可能会导致数据丢失\n\n您确定要离开吗?"; Unlo ...

  10. chrome.declarativeWebRequest

    chrome.declarativeWebRequest 清单文件 规则 条件与操作的求值 使用优先级覆盖规则 类型 HeaderFilter RequestMatcher CancelRequest ...