/*
平台和砖块的坐标离散化,边缘坐标转换成单位长度
处理下落信息,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<<
3],cnt,tot;
//离散化
ll sum[maxn<<
2],lazy[maxn],flag[maxn];
//flag维护区间是否置零,优先级大于lazy
inline
void pushup(
int rt){
sum[rt]=sum[rt<<
1]+sum[rt<<
1|
1];
}
inline void pushdown(
int l,
int r,
int rt){
if(flag[rt]){
sum[rt<<
1]=sum[rt<<
1|
1]=
0;
flag[rt<<
1]=flag[rt<<
1|
1]=
1;
flag[rt]=
0;
}
else if(lazy[rt]){
int m=l+r>>
1;
lazy[rt<<
1]=lazy[rt<<
1|
1]=
lazy[rt];
sum[rt<<
1]+=lazy[rt]*(data[m]-data[l]+
1);
sum[rt<<
1|
1]+=lazy[rt]*(data[r]-
data[m]);
lazy[rt]=
0;
}
}
void setzero(
int L,
int R,
int l,
int r,
int rt){
if(L<=l && R>=
r){
sum[rt]=
0;
lazy[rt]=
0;
flag[rt]=
1;
return;
}
pushdown(l,r,rt);
int m=l+r>>
1;
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]=
0;
if(l==r)
return;
int m=l+r>>
1;
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]+
1;
return;
}
pushdown(l,r,rt);
int m=l+r>>
1;
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>>
1;
ll ret=
0;
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)==
2){
tot=cnt=
0;
for(
int i=
0;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=
0;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=
1;i<cnt;i++
)
if(data[i]-data[i-
1]>
1) data[tmp++]=data[i-
1]+
1;
cnt=
tmp;
sort(data,data+
cnt);
tot=unique(data,data+cnt)-
data;
sort(bds,bds+
m);
build(0,tot,
1);
for(
int i=
0;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,0,tot,
1);
}
//每次查询后
for(
int i=
0;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,
0,tot,
1);
setzero(L,R,0,tot,
1);
}
for(
int i=
0;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<<
4],flag[maxn<<
4];
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<<
1]=flag[k<<
1|
1]=
flag[k];
flag[k]=
0;
}
if(sum[k]){
sum[k<<
1]+=
sum[k];
sum[k<<
1|
1]+=
sum[k];
sum[k]=
0;
}
}
//这个函数染色
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>>
1;
//注意这里不可以等于,因为维护区间[l1,l1]没有任何意义
if(l1<mid) modify1(k<<
1,left,mid,l1,r1,x);
if(r1>mid) modify1(k<<
1|
1,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>>
1;
if(l1<mid) modify2(k<<
1,left,mid,l1,r1);
if(r1>mid) modify2(k<<
1|
1,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+
1==right)
//判断退出递归并不是通过判断(l==r)
return;
pushdown(k);
int mid=left+right>>
1;
query(k<<
1,left,mid);
query(k<<
1|
1,mid,right);
}
int main(){
int n,m;
while(scanf(
"%d%d",&n,&m)==
2){
a.clear();
//build()=init()
memset(sum,
0,
sizeof sum);
memset(flag,0,
sizeof flag);
memset(res,0,
sizeof res);
for(
int i=
1;i<=n;i++
){
scanf("%d%d",&l[i],&
r[i]);
a.push_back(l[i]);
a.push_back(r[i]);
}
for(
int i=
1;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+
1,b+
1+
m,cmp);
for(
int i=
1;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(1,
0,cnt-
1,pos1,pos2,b[i].id);
}
for(
int i=
1;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(1,
0,cnt-
1,pos1,pos2);
}
query(1,
0,cnt-
1);
for(
int i=
1;i<=m;i++
)
printf("%lld\n",res[i]);
puts("");
}
return 0;
}
转载于:https://www.cnblogs.com/zsben991126/p/9929694.html