中文题,就不解释了
刚好前几天的多校出过类似的题,当时没学过树状数组,想了好久才想出了一个办法,复杂度为O(n),比树状数组复杂度低。
方法一 (复杂度O(n))
用个数组标记区间的头加个权值,尾减个权值。
代码:
//time 248ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100000+100;
int a[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==0)
break;
int x,y;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
a[x]++;
a[y+1]--;
}
for(int i=1;i<=n;i++)
{
a[i]=a[i-1]+a[i];
}
printf("%d",a[1]);
for(int i=2;i<=n;i++)
printf(" %d",a[i]);
printf("\n");
}
return 0;
}
方法二:树状数组
//time 275ms
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=100000+1000;
int a[maxn];
int n;
int low(int k)
{
return k&(-k);
}
void update(int k,int v)
{
while(k<=n)
{
a[k]+=v;
k+=low(k);
}
}
int sum(int i)
{
int ans=0;
while(i>0)
{
ans+=a[i];
i-=low(i);
}
return ans;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)
break;
int x,y;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
update(x,1);
update(y+1,-1);
}
printf("%d",sum(1));
for(int i=2;i<=n;i++)
printf(" %d",sum(i));
printf("\n");
}
}