从大前天开始系统的学习了一下线段树,总结了一些技巧,刷了几道题- -
话不多说,开始表演。
题目大意是初始区间为1,给定区间【l,r】,区间每个数+1。再给m个询问,询问【l,r】区间的和。
建树。(用模板)
对于区间更新,我们可以先不更新子区间的值,而是加一个懒惰标记。若更新或查询的是子区间的话,就把懒惰标记往下传,并清空当前节点的标记,再依次push up。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int n,m,t,l,r;
struct node{
int l,r;
long long sum,lazy;
void update(int x)
{
sum += (r-l+1)*x;
lazy += x;
}
}tree[maxn*4];
void push_up(int x)
{
tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
}
void push_down(int x)
{
int lazyval = tree[x].lazy;
if(lazyval){
tree[x<<1].update(lazyval);
tree[x<<1|1].update(lazyval);
tree[x].lazy = 0;
}
}
void build(int x,int l,int r)
{
tree[x].l = l,tree[x].r = r;
tree[x].sum = tree[x].lazy = 0;
if(l==r) tree[x].sum = 0;
else{
int mid = (l+r)/2;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
}
}
void update(int x,int l,int r)
{
int L=tree[x].l,R=tree[x].r;
if(l<=L&&r>=R)
tree[x].update(1);
else{
push_down(x);
int mid = (L+R)/2;
if(l<=mid)
update(x<<1,l,r);
if(r>mid)
update(x<<1|1,l,r);
push_up(x);
}
}
long long query(int x,int l,int r)
{
int L=tree[x].l,R=tree[x].r;
long long ans = 0;
if(l<=L&&r>=R)
ans += tree[x].sum;
else{
push_down(x);
// cout<<tree[2].sum<<" id"<<2<<endl;
// cout<<tree[5].sum<<" id"<<5<<endl;
// cout<<tree[4].sum<<" id"<<4<<endl;
int mid = (L+R)/2;
if(l<=mid)
ans+=query(x<<1,l,r);
if(r>mid)
ans+=query(x<<1|1,l,r);
push_up(x);
//cout<<ans<<endl;
}
return ans;
}
int main()
{
//freopen("d://test.txt","r",stdin);
while(~scanf("%d%d%d",&n,&m,&t))
{
build(1,1,n);
for(int i=0;i<m;i++)
{
scanf("%d%d", &l, &r);
update(1,l,r);
}
// for(int i=1;i<=n;i++)
// cout<<tree[i].sum<<endl;
for(int i=0;i<t;i++)
{
scanf("%d%d",&l,&r);
cout<<query(1,l,r)<<endl;
}
//cout<<tree[3].sum;
}
return 0;
}
本文详细介绍线段树的基本概念及其实现技巧,通过具体题目演示如何利用线段树进行区间更新与查询操作,适用于算法竞赛及数据结构初学者。

7087

被折叠的 条评论
为什么被折叠?



