HDU1556 - Color the ball - 前缀和/线段树/树状数组
思路
周赛的一开始直接用book进行标记,后来TLE,然后改成map,继续TLE
后来想到用线段树写,但是没写对;想用树状数组写,结果发现不会写
AC代码(前缀和)
//前缀和的做法
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int N=100020;
int a[N];
int sum[N];
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
memset(a,0,sizeof(a));
int aa,bb;
for(int i=0; i<n; i++)
{
scanf("%d %d",&aa,&bb);
// a[aa]=a[aa]+1;
// a[bb+1]=a[bb+1]-1;
a[aa]++;
a[bb+1]--;
}
//求前缀和
sum[0]=0;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
for(int i=1;i<n;i++)
printf("%d ",sum[i]);
printf("%d\n",sum[n]);
}
return 0;
}
AC代码(线段树)
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int N=100020;
int a[4*N];
int ans[4*N];
int p;
//void pushdown(int i,int len)
//{
// if(lazy[i])
// {
// lazy[i<<1]=lazy[i];
// lazy[i<<1|1]=lazy[i];
// a[i<<1]=(len-(len>>1))*lazy[i];
// a[i<<1|1]=(len>>1)*lazy[i];
// lazy[i]=0;
// }
//}
void pushdown(int i)
{
a[i<<1]+=a[i];
a[i<<1|1]+=a[i];
}
//void build(int L,int R,int i)
//{
// if(L==R)
// {
// a[i]=0;
// return;
// }
// int mid=(L+R)>>1;
// build(L,mid,i<<1);
// build(mid+1,R,i<<1|1);
// a[i]=a[i<<1]+a[i<<1|1];
//}
void update(int left,int right,int L,int R,int i)
{
if(left<=L&&right>=R)
{
// lazy[i]+=1;
// a[i]=R-L+1;
a[i]++;
return;
}
// pushdown(i,R-L+1);
int mid=(R+L)>>1;
if(left<=mid)
update(left,right,L,mid,i<<1);
if(right>mid)
update(left,right,mid+1,R,i<<1|1);
// a[i]=a[i<<1]+a[i<<1|1];
}
void query(int L,int R,int i)
{
if(L==R)
{
ans[p++]=a[i];
return;
}
int mid=(L+R)>>1;
pushdown(i);
query(L,mid,i<<1);
query(mid+1,R,i<<1|1);
}
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
memset(a,0,sizeof(a));
memset(ans,0,sizeof(ans));
// build(1,n,1);
int aa,bb;
p=0;
for(int i=0; i<n; i++)
{
scanf("%d %d",&aa,&bb);
// if(aa==bb)
// {
// a[aa]++;
// continue;
// }
update(aa,bb,1,n,1);
}
query(1,n,1);
for(int i=0; i<n-1; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n-1]);
}
return 0;
}