题目链接: Color the ball
思路
已经写过一次类似前缀和的题解了,这次再写一遍线段树或树状数组的解法。这题是区间更新和单点查询,线段树的单点查询不过是区间查询的特殊形式,代码是一样的。但是树状数组的区间更新和单点查询却不同于区间更新和区间查询。不过此处就不详细说了,树状数组本身就是个神奇的东西。
1.线段树
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
int addmark[450000],seqtree[450000];
void maketree(int node,int begin,int end)
{
addmark[node]=0;
if(begin==end)
{
seqtree[node]=0;
return;
}
int mid=(begin+end)/2;
maketree(2*node,begin,mid);
maketree(2*node+1,mid+1,end);
seqtree[node]=seqtree[2*node]+seqtree[2*node+1];
}
void pushdown(int node,int begin,int end)
{
if(!addmark[node])
return;
int mid=(begin+end)/2;
addmark[2*node]+=addmark[node];
addmark[2*node+1]+=addmark[node];
seqtree[2*node]+=(mid-begin+1)*addmark[node];
seqtree[2*node+1]+=(end-mid)*addmark[node];
addmark[node]=0;
}
void update(int node,int begin,int end,int left,int right,int k)
{
int mid=(begin+end)/2;
if(left>end || right<begin)
return;
if(left<=begin && right>=end)
{
addmark[node]+=k;
seqtree[node]+=(end-begin+1)*k;
return;
}
pushdown(node,begin,end);
update(2*node,begin,mid,left,right,k);
update(2*node+1,mid+1,end,left,right,k);
seqtree[node]=seqtree[2*node]+seqtree[2*node+1];
}
int query(int node,int begin,int end,int left,int right)
{
if(left>end || right<begin)
return 0;
if(left<=begin && right>=end)
{
return seqtree[node];
}
pushdown(node,begin,end);
int mid=(begin+end)/2,sum=0;
sum+=query(2*node,begin,mid,left,right);
sum+=query(2*node+1,mid+1,end,left,right);
return sum;
}
int main()
{
int n,i,A,B;
while(scanf("%d",&n)!=EOF && n)
{
memset(seqtree,0,sizeof(seqtree));
memset(addmark,0,sizeof(addmark));
maketree(1,1,n);
for(i=1;i<=n;i++)
{
scanf("%d %d",&A,&B);
update(1,1,n,A,B,1);
}
for(i=1;i<=n;i++)
printf("%d%c",query(1,1,n,i,i),(i==n)?'\n':' ');
}
}
2.树状数组
#include <bits/stdc++.h>
using namespace std;
int n,tree[100001];
int lowbit(int x)
{
return (x&(-x));
}
int update(int x,int k)
{
int sum=0;
for(int i=x; i<=n ;i=i+lowbit(i))
{
tree[i]+=k;
}
return sum;
}
int query(int x)
{
int sum=0;
for(int i=x;i>0;i=i-lowbit(i))
{
sum+=tree[i];
}
return sum;
}
int main()
{
int i,A,B;
while(cin>>n && n)
{
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
cin>>A>>B;
update(A,1);
update(B+1,-1);
}
for(i=1;i<=n;i++)
{
if(i==1)
printf("%d",query(i));
else
printf(" %d",query(i));
}
cout<<endl;
}
}