线段树(二)区间更新
2015-08-10 14:55
417 查看
hdu 1698
调试了很久,没想到一次ac了。
注意:区间更新中用到一种技术,延迟更新pushdown(v)。如果不使用延迟更新,而一个个的更新,长度为n的区间更新需要nlogn,而数组直接更新只需要n。体现不出线段树的优势,容易超时。
需要注意的另一点,建树的时候所有节点的状态都要考虑好,由于我做这题时,没有考虑好内节点的状态,导致样例跑出23的结果。这发代码可以当做模板来用。
区间更新线段树通常会出现一个段内的值(颜色等)不同的情况,需要进行标记清楚。
付ac代码:
#include<iostream>
#include<fstream>
#include<set>
#include<stack>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX=0xfffffff;
const int mx=110000;
struct node{
int l,r,col;
}tree[mx*4];
void pushdown(int v)
{
if(tree[v].col!=-1)
{
tree[v*2].col=tree[v*2+1].col=tree[v].col;
tree[v].col=-1;
}
}
void build(int v,int l,int r)
{
tree[v].l=l,tree[v].r=r,tree[v].col=1;
if(l==r)
{
return;
}
int mid=(l+r)/2;build(v*2,l,mid),build(v*2+1,mid+1,r);
}
void update(int v,int l,int r,int col)
{
if(tree[v].col==col) return;
if(tree[v].l==l&&tree[v].r==r)
{
tree[v].col=col;
return ;
}
pushdown(v);
int mid=(tree[v].l+tree[v].r)/2;
if(l>mid) update(v*2+1,l,r,col);
else if(r<=mid) update(v*2,l,r,col);
else
{
update(v*2,l,mid,col);
update(v*2+1,mid+1,r,col);
}
}
int ans;
void query(int v,int l,int r)
{
if(tree[v].l==l&&tree[v].r==r&&tree[v].col!=-1)
{
ans+=(tree[v].col)*(tree[v].r-tree[v].l+1);
return ;
}
pushdown(v);
int mid=(tree[v].l+tree[v].r)/2;
if(l>mid) query(v*2+1,l,r);
else if(r<=mid) query(v*2,l,r);
else
{
query(v*2,l,mid);
query(v*2+1,mid+1,r);
}
}
int main( )
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
int n,q;
scanf("%d%d",&n,&q);
build(1,1,n);
for(int i=1;i<=q;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
update(1,x,y,z);
}
ans=0;
query(1,1,n);
printf("Case %d: The total value of the hook is %d.\n",ca,ans);
}
return 0;
}
调试了很久,没想到一次ac了。
注意:区间更新中用到一种技术,延迟更新pushdown(v)。如果不使用延迟更新,而一个个的更新,长度为n的区间更新需要nlogn,而数组直接更新只需要n。体现不出线段树的优势,容易超时。
需要注意的另一点,建树的时候所有节点的状态都要考虑好,由于我做这题时,没有考虑好内节点的状态,导致样例跑出23的结果。这发代码可以当做模板来用。
区间更新线段树通常会出现一个段内的值(颜色等)不同的情况,需要进行标记清楚。
付ac代码:
#include<iostream>
#include<fstream>
#include<set>
#include<stack>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX=0xfffffff;
const int mx=110000;
struct node{
int l,r,col;
}tree[mx*4];
void pushdown(int v)
{
if(tree[v].col!=-1)
{
tree[v*2].col=tree[v*2+1].col=tree[v].col;
tree[v].col=-1;
}
}
void build(int v,int l,int r)
{
tree[v].l=l,tree[v].r=r,tree[v].col=1;
if(l==r)
{
return;
}
int mid=(l+r)/2;build(v*2,l,mid),build(v*2+1,mid+1,r);
}
void update(int v,int l,int r,int col)
{
if(tree[v].col==col) return;
if(tree[v].l==l&&tree[v].r==r)
{
tree[v].col=col;
return ;
}
pushdown(v);
int mid=(tree[v].l+tree[v].r)/2;
if(l>mid) update(v*2+1,l,r,col);
else if(r<=mid) update(v*2,l,r,col);
else
{
update(v*2,l,mid,col);
update(v*2+1,mid+1,r,col);
}
}
int ans;
void query(int v,int l,int r)
{
if(tree[v].l==l&&tree[v].r==r&&tree[v].col!=-1)
{
ans+=(tree[v].col)*(tree[v].r-tree[v].l+1);
return ;
}
pushdown(v);
int mid=(tree[v].l+tree[v].r)/2;
if(l>mid) query(v*2+1,l,r);
else if(r<=mid) query(v*2,l,r);
else
{
query(v*2,l,mid);
query(v*2+1,mid+1,r);
}
}
int main( )
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
int n,q;
scanf("%d%d",&n,&q);
build(1,1,n);
for(int i=1;i<=q;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
update(1,x,y,z);
}
ans=0;
query(1,1,n);
printf("Case %d: The total value of the hook is %d.\n",ca,ans);
}
return 0;
}
相关文章推荐
- 静态代码块,构造代码块和构造函数的区别
- 中文分词与停用词的作用
- Java开发web的几种开发模式
- Retrofit 介绍
- apache tomcat集群
- QT调用CHM方法
- shared_ptr/unique_ptr一点体会
- #笔记#圣思园 JavaWeb 第2讲——CSS层叠样式表Cascading Style Sheets
- find 常用命令
- python测试框架总结
- 插件启动顺序控制
- 卫星式菜单
- hyundai-wia
- 根据服务器端返回的字符数组,展示字符串标签,需要涉及字符串长度处理以及字符串换行,字符串不够一行自动跳到第二行的逻辑
- python测试框架总结
- Android技能杂谈——如何优雅的处理控件的点击事件
- 数据库设计三大范式简析
- Kinect2.0+EmguCV获取景深图
- jQuery右下角旋转环状菜单特效代码
- Caffe源码(二):blob 分析