/*
平台和砖块的坐标离散化,边缘坐标转换成单位长度
处理下落信息,sum数组维护区间的砖块数量
把平台按高度从高到低排序,询问平台区间的砖块有多少,询问后将该区域砖块数置0
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
struct Blocks{
int l,r;
}bks[maxn];//砖块信息
struct Boards{
int l,r,h,id;
bool operator<(const Boards & a)const{
return h>a.h;
}
}bds[maxn];//平台信息
ll ans[maxn];
int data[maxn<<],cnt,tot;//离散化
ll sum[maxn<<],lazy[maxn],flag[maxn];//flag维护区间是否置零,优先级大于lazy
inline void pushup(int rt){
sum[rt]=sum[rt<<]+sum[rt<<|];
}
inline void pushdown(int l,int r,int rt){
if(flag[rt]){
sum[rt<<]=sum[rt<<|]=;
flag[rt<<]=flag[rt<<|]=;
flag[rt]=;
}
else if(lazy[rt]){
int m=l+r>>;
lazy[rt<<]=lazy[rt<<|]=lazy[rt];
sum[rt<<]+=lazy[rt]*(data[m]-data[l]+);
sum[rt<<|]+=lazy[rt]*(data[r]-data[m]);
lazy[rt]=;
}
}
void setzero(int L,int R,int l,int r,int rt){
if(L<=l && R>=r){
sum[rt]=;
lazy[rt]=;
flag[rt]=;
return;
}
pushdown(l,r,rt);
int m=l+r>>;
if(L<=m) setzero(L,R,lson);
if(R>m) setzero(L,R,rson);
pushup(rt);
}
void build(int l,int r,int rt){
sum[rt]=lazy[rt]=flag[rt]=;
if(l==r) return;
int m=l+r>>;
build(lson);build(rson);
}
void update(int L,int R,int l,int r,int rt){
if(L<=l && R>=r){
lazy[rt]++;
sum[rt]+=data[r]-data[l]+;
return;
}
pushdown(l,r,rt);
int m=l+r>>;
if(L<=m) update(L,R,lson);
if(R>m) update(L,R,rson);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
if(L<=l && R>=r){
return sum[rt];
}
pushdown(l,r,rt);
int m=l+r>>;
ll ret=;
if(L<=m) ret+=query(L,R,lson);
if(R>m) ret+=query(L,R,rson);
return ret;
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)==){
tot=cnt=;
for(int i=;i<n;i++){
scanf("%d%d",&bks[i].l,&bks[i].r);
bks[i].r--;
data[cnt++]=bks[i].l;
data[cnt++]=bks[i].r;
}
for(int i=;i<m;i++){
scanf("%d%d%d",&bds[i].l,&bds[i].r,&bds[i].h);
bds[i].id=i;
bds[i].r--;
data[cnt++]=bds[i].l;
data[cnt++]=bds[i].r;
}
int tmp=cnt;
sort(data,data+cnt);
for(int i=;i<cnt;i++)
if(data[i]-data[i-]>) data[tmp++]=data[i-]+;
cnt=tmp;
sort(data,data+cnt);
tot=unique(data,data+cnt)-data;
sort(bds,bds+m); build(,tot,);
for(int i=;i<n;i++){
int L=lower_bound(data,data+tot,bks[i].l)-data;
int R=lower_bound(data,data+tot,bks[i].r)-data;
update(L,R,,tot,);
}
//每次查询后
for(int i=;i<m;i++){
int L=lower_bound(data,data+tot,bds[i].l)-data;
int R=lower_bound(data,data+tot,bds[i].r)-data;
ans[bds[i].id]=query(L,R,,tot,);
setzero(L,R,,tot,);
}
for(int i=;i<m;i++)
printf("%lld\n",ans[i]);
}
}

碰到区间更新最头痛的就是坐标的离散化,所以上面的代码挂了

网上看题解,线段树有直接维护坐标的办法,但是维护方式和普通的区间更新略有不同

同时换了种比较容易懂的思路

/*
对于坐标轴上的离散化,与段的离散化有所不同,但也可以直接离散化而不用进行其它修改,其在线段树上的维护方式为[l,m],[m,r],同时分左右子树进行更新时判断条件也相应改变
比较快的做法,给横轴染色,然后再统计掉在每种颜色的砖头有几块
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 100005
#define ll long long
struct board{
int l,r,h,id;
}b[maxn];
int n,m,l[maxn],r[maxn];
ll res[maxn];
ll sum[maxn<<],flag[maxn<<];
vector<int> a;
bool cmp(const board &a,const board &b){
return a.h<b.h;
}
void pushdown(int k){
if(flag[k]){
flag[k<<]=flag[k<<|]=flag[k];
flag[k]=;
}
if(sum[k]){
sum[k<<]+=sum[k];
sum[k<<|]+=sum[k];
sum[k]=;
}
}
//这个函数染色
void modify1(int k,int left,int right,int l1,int r1,int x){
if(l1<=left && r1>=right){
flag[k]=x;
return;
}
pushdown(k);
int mid=left+right>>;
//注意这里不可以等于,因为维护区间[l1,l1]没有任何意义
if(l1<mid) modify1(k<<,left,mid,l1,r1,x);
if(r1>mid) modify1(k<<|,mid,right,l1,r1,x);
}
//这个函数进行累加
void modify2(int k,int left,int right,int l1,int r1){
if(l1<=left && right<=r1){
sum[k]++;
return;
}
pushdown(k);
int mid=left+right>>;
if(l1<mid) modify2(k<<,left,mid,l1,r1);
if(r1>mid) modify2(k<<|,mid,right,l1,r1);
}
//统计
void query(int k,int left,int right){
if(flag[k]){
//因为直接维护坐标,所以两坐标直接相减
res[flag[k]]+=(ll)sum[k]*(a[right]-a[left]);
return;
}
if(left+==right)//判断退出递归并不是通过判断(l==r)
return;
pushdown(k);
int mid=left+right>>;
query(k<<,left,mid);
query(k<<|,mid,right);
} int main(){
int n,m;
while(scanf("%d%d",&n,&m)==){
a.clear();
//build()=init()
memset(sum,,sizeof sum);
memset(flag,,sizeof flag);
memset(res,,sizeof res); for(int i=;i<=n;i++){
scanf("%d%d",&l[i],&r[i]);
a.push_back(l[i]);
a.push_back(r[i]);
}
for(int i=;i<=m;i++){
scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].h);
b[i].id=i;
a.push_back(b[i].l);
a.push_back(b[i].r);
}
sort(a.begin(), a.end());
a.erase(unique(a.begin(),a.end()),a.end());
int cnt=a.size(); sort(b+,b++m,cmp);
for(int i=;i<=m;i++){
int pos1=lower_bound(a.begin(),a.end(),b[i].l)-a.begin();
int pos2=lower_bound(a.begin(),a.end(),b[i].r)-a.begin();
modify1(,,cnt-,pos1,pos2,b[i].id);
}
for(int i=;i<=n;i++){
int pos1=lower_bound(a.begin(),a.end(),l[i])-a.begin();
int pos2=lower_bound(a.begin(),a.end(),r[i])-a.begin();
modify2(,,cnt-,pos1,pos2);
}
query(,,cnt-);
for(int i=;i<=m;i++)
printf("%lld\n",res[i]);
puts("");
}
return ;
}

zoj3299 线段树区间更新,坐标建立线段树的方式的更多相关文章

  1. hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

    #1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题 ...

  2. POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)

    POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...

  3. poj 3468 A Simple Problem with Integers (线段树区间更新求和lazy思想)

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

  4. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

  5. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...

  6. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  7. HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...

  8. HDU 1698 线段树 区间更新求和

    一开始这条链子全都是1 #include<stdio.h> #include<string.h> #include<algorithm> #include<m ...

  9. poj 3468 线段树区间更新/查询

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  10. POJ-2528 Mayor's posters (线段树区间更新+离散化)

    题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...

随机推荐

  1. Keepalive+nginx实现高可用负载均衡方案

    Keepalive+nginx实现高可用负载均衡方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.nginx做高可用工作在第几层? 上个月我发表了一篇keepalive+lv ...

  2. Linux记录-筛选日志sed、find、tail,du,awk命令

    1.查看某一段时间的日志 #cat hdfs-audit.log | sed -n '/2018-04-11 10:00:00/,/2018-04-11 10:01:00/ p' | more   - ...

  3. Kruskal算法:最小生成树

    //Kruskal算法按照边的权值从小到大查看一遍,如果不产生圈(重边等也算在内),就把当前这条表加入到生成树中. //如果判断是否产生圈.假设现在要把连接顶点u和顶点v的边e加入生成树中.如果加入之 ...

  4. 用Python中的re做信息筛选

    背景 平时工作中,我们经常会处理大量的元数据(Raw Data),而一般的文件编辑器只能一次查询一个关键字,这就难以连续的分析元数据,比如分析产品日志文件(log),日志可能包括很多informati ...

  5. 16. Spring boot 错误页面

      默认效果:1).浏览器,返回一个默认的错误页面 1.1 请求头 1.2返回结果 2).如果是其他客户端,默认响应一个json数据 2.1请求头 2.2返回结果 { "timestamp& ...

  6. 设置通过Maven创建的工程的JDK版本—一劳永逸

    设置通过Maven创建的工程的JDK版本—一劳永逸 [1]打开settings.xml文件 [2]找到profiles标签 [3]加入一下配置   <profile> <id> ...

  7. 关于形如--error LNK2005: xxx 已经在 msvcrtd.lib ( MSVCR90D.dll ) 中定义--的问题分析解决

    转自:http://hi.baidu.com/qinfengxiaoyue/item/ff262ccfb53b4c2ba0b50a89 引自:http://blog.csdn.net/sptoor/a ...

  8. MongoDB的基本概念

    MongoDB的基本概念 库 db就是数据库 文档就是数据表的行 集合就是数据表,这个没有模式,啥叫没有模式呢,就是没有列的定义,随便什么属性都行,这点就比关系行数据库牛逼10000000倍,逆天了.

  9. [转]GDB-----2.watchpoint

    TODO需要在ARM下验证 1. 前言 watchpoint,顾名思义,其一般用来观察某个变量/内存地址的状态(也可以是表达式),如可以监控该变量/内存值是否被程序读/写情况. 在gdb中可通过下面的 ...

  10. lxde 的安装和卸载以及注意事项,lubuntu

    安装: $ sudo apt install lxde $ sudo apt install lxde-common 安装完毕后,可能没法关机及logout,可以使用如下安装: $ sudo apt ...