两道树状数组题。

推荐一篇介绍树状数组比较好的博客:http://www.cnblogs.com/yykkciwei/archive/2009/05/08/1452889.html

hdu 4000 Fruit Ninja

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4000

思路:对每个位置处理,考虑后面有多少比他大的数,则该位置上的数与后面两个大数可构成x*(x-1)/2种,再把所有的i<j<k && a[i]<a[j]<a[k]除去。

code:

# include<stdio.h>
# include<string.h>
# define Mod 100000007
int count[100005],n;
__int64 ans;
void insert(int i)
{
	while(i<=n)
	{
		count[i]++;
		i+= i&(-i);
	}
}
int query(int i)
{
	int num=0;
	while(i>0)
	{
		num+=count[i];
		i-=i&(-i);
	}
	return num;
}
int main()
{
	int i,ncase,t,a;
	__int64 tmp1,tmp2;
	scanf("%d",&ncase);
	for(t=1;t<=ncase;t++)
	{
		scanf("%d",&n);
		memset(count,0,sizeof(count));
		ans=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a);
			insert(a);
			tmp1=query(a-1);//扫描比a小的数
			tmp2=n-a-(i-tmp1-1);//在a后面比a大的数
			ans-=tmp1*tmp2;//除去i<j<k && a[i]<a[j]<a[k]的情况
			if(tmp2>=2) ans+=tmp2*(tmp2-1)/2;
		}
		printf("Case #%d: %d\n",t,ans%Mod);
	}
	return 0;
}

 

hdu  4020 Ads Proposal

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4020

可以用模拟预处理,感觉时间复杂度也不是很高,虽然AC了但4000+ms,估计数据量特别大。

此题也是树状数组。先把所有的广告根据点击次数从大到小进行排序,然后每处理一条广告,判断该条广告是这个人的第几天广告,然后把该条广告的长度作为增量增加到一个数组上!

code:

# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# define M 500005
__int64 sum[M];
int m,visit[100005];
struct node{
    int id,c,len;
}s[M];
int Lowbit(int i)
{
    return i&(-i);
}
void puls(int i,int num)
{
    while(i<=m)
    {
        sum[i]+=num;
        i+=Lowbit(i);
    }
}
__int64 getsum(int i)
{
    __int64 ans=0;
    while(i>0)
    {
        ans+=sum[i];
        i-=Lowbit(i);
    }
    return ans;
}
int cmp(const void *a,const void *b)
{
    struct node *c=(struct node *)a;
    struct node *d=(struct node *)b;
    return d->c - c->c;
}
int main()
{
    int i,n,Q,ncase,t,k;
    scanf("%d",&ncase);
    for(t=1;t<=ncase;t++)
    {
        scanf("%d%d%d",&n,&m,&Q);
        for(i=1;i<=m;i++)
            scanf("%d%d%d",&s[i].id,&s[i].c,&s[i].len);
        qsort(s+1,m,sizeof(s[1]),cmp);
        memset(visit,0,sizeof(visit));
        memset(sum,0,sizeof(sum));
        for(i=1;i<=m;i++)
        {
            visit[s[i].id]++;
            puls(visit[s[i].id],s[i].len);
        }
        printf("Case #%d:\n",t);
        while(Q--)
        {
            scanf("%d",&k);
            if(k>m) k=m;
            printf("%I64d\n",getsum(k));
        }
    }
    return 0;
}

感觉写的也没错啊。。不过交了之后仍然4000ms+,很是无语~~

posted on 2011-09-27 10:55  奋斗青春  阅读(740)  评论(0编辑  收藏  举报