HDU 1556 线段树或树状数组,插段求点

时间:2023-03-09 00:25:08
HDU 1556  线段树或树状数组,插段求点

1、HDU 1556  Color the ball   区间更新,单点查询

2、题意:n个气球,每次给(a,b)区间的气球涂一次色,问最后每个气球各涂了几次。

(1)树状数组

总结:树状数组是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值。

这里改下思路可以用树状数组。在更新(a,b)时,向上更新,将a~n加1,b+1~n减1。查询点时,向下求和即可。

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=,MAX=; int n,c[MAX]; int lowbit(int x) {
//计算2^k
return x&-x;
} void update(int x,int val)
{
//向上更新,使所有包含了x的区间都更新一下
while(x<=n) {
c[x]+=val;
x+=lowbit(x);
}
} int Sum(int x)
{
//向下查询
int sum=;
while(x>) {
sum+=c[x];
x-=lowbit(x);
}
return sum;
} int main()
{
while(~scanf("%d",&n),n) {
mes(c,);
int a,b;
FF(i,,n) {
scanf("%d%d",&a,&b);
update(a,);
update(b+,-);
}
F(i,,n) printf("%d ",Sum(i));
printf("%d\n",Sum(n));
} return ;
}

(2)线段树+lazy思想

总结:lazy,更新时只到区间,可以节省很多时间。

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=,MAX=; int n,c[MAX<<]; void build(int o,int L,int R)
{
c[o]=;
if(L==R) return ;
int mid=(L+R)>>;
build(o<<,L,mid);
build(o<<|,mid+,R);
} void update(int o,int l,int r,int L,int R)
{
if(l<=L&&R<=r) { c[o]++; return ; } //关键:只更新到区间,一开始更新到每个单独的点,果断T了,//然后用l==L&&R==r,又果断MLE
int mid=(L+R)>>;
if(mid<l) update(o<<|,l,r,mid+,R);
else if(r<=mid) update(o<<,l,r,L,mid);
else {
update(o<<,l,r,L,mid);
update(o<<|,l,r,mid+,R);
}
} int ans[MAX];
void query(int o,int L,int R)
{
if(c[o]) {
for(int i=L; i<=R; i++)
ans[i]+=c[o]; //也是lazy思想,标记了的区间就加上
}
if(L==R) return ; //询问时还是要到点
int mid=(L+R)>>;
query(o<<,L,mid);
query(o<<|,mid+,R);
} int main()
{
while(~scanf("%d",&n) ,n )
{
build(,,n);
fill(ans+,ans++n,); //fil函数
int a,b;
FF(i,,n) {
scanf("%d%d",&a,&b);
update(,a,b,,n);
}
query(,,n);
F(i,,n) printf("%d ",ans[i]);
printf("%d\n",ans[n]);
} return ;
}