题意很清晰,n次操作,每次操作对a到b区间进行一次染色,最后输出每个点染色的次数。就是对区间进行更新然后查找,只不过最后查找的是点,可以用线段树也可以用树状数组来处理。都是改下模板就可以过了。
线段树做法:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
struct node
{
int l;
int r;
long long sum;
long long mark;
}s[300000];
void pushup(int k)
{
s[k].sum=s[k<<1].sum+s[(k<<1)+1].sum;
}
void pushdown(int k,int d)
{
if(s[k].mark)
{
s[k<<1].mark+=s[k].mark;
s[(k<<1)+1].mark+=s[k].mark;
s[k<<1].sum+=s[k].mark*(d-(d>>1));
s[(k<<1)+1].sum+=s[k].mark*(d>>1);
s[k].mark=0;
}
}
void init(int l,int r,int k)
{
s[k].l=l;
s[k].r=r;
s[k].mark=0;
if(l==r)
{
s[k].sum=0;
return ;
}
int mid=(l+r)/2;
init(l,mid,k<<1);
init(mid+1,r,(k<<1)+1);
pushup(k);
}
long long query(int l,int r,int k)
{
if(l<=s[k].l&&r>=s[k].r)
{
return s[k].sum;
}
pushdown(k,s[k].r-s[k].l+1);
int mid=(s[k].l+s[k].r)/2;
long long res=0;
if(l<=mid)
res+=query(l,r,(k<<1));
if(r>mid)
res+=query(l,r,(k<<1)+1);
return res;
}
void update(int l,int r,int c,int k)
{
if(l<=s[k].l&&r>=s[k].r)
{
s[k].mark+=c;
s[k].sum+=(c*(s[k].r-s[k].l+1));
return ;
}
pushdown(k,s[k].r-s[k].l+1);
int mid=(s[k].l+s[k].r)/2;
if(l<=mid)
update(l,r,c,k<<1);
if(r>mid)
update(l,r,c,(k<<1)+1);
pushup(k);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
init(1,n,1);
for(int i=0;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
update(a,b,1,1);
}
long long num=query(1,1,1);
cout<<num;
for(int i=2;i<=n;i++)
{
long long num=query(i,i,1);
cout<<" "<<num;
}
cout<<endl;
}
return 0;
}
树状数组做法:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int c[100005];
int n;
void add(int k,int num)
{
while(k<=n)
{
c[k]+=num;
k+=k&-k;
}
}
int read(int k)
{
int sum=0;
while(k)
{
sum+=c[k];
k-=k&-k;
}
return sum;
}
int main()
{
int a,b;
int i;
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof(c));
if(n==0)
break;
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
add(a,1);
add(b+1,-1);
}
for(i=1;i<n;i++)
{
cout<<read(i)<<" ";
}
cout<<read(n)<<endl;
}
return 0;
}