poj1990 MooFest && hdu3015 Disharmony Trees (树状数组)

题目:http://poj.org/problem?id=1990 && http://acm.hdu.edu.cn/showproblem.php?pid=3015

题意:这两题题目意思差不多,只说下poj1990的。告诉每只牛的位置xi以及耳聋程度vi,和两只牛进行交流需要的音量s=abs(xi-xj)*max(vi,vj),求每头牛两两(n*(n-1)/2)交流需要的总音量。

分析:对于任意一头牛Ci找比它耳聋程度低的牛,那么再找到每头牛到xi的距离的和S就行了。S=比xi大的位置的和-比xi大的位置的个数*xi+比xi小的位置的个数*xi-比xi小的位置的和。算个数以及位置的和,分别用两个树状数组统计就行了。

poj1990代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxn = 20048;
int lowbit[maxn],tree[maxn],cnt[maxn];

struct node
{
	int v;
	int pos;
	bool operator < (const node &t) const
	{
		return v<t.v;
	}
}s[maxn];

void CalLowbit()
{
	for(int i=1;i<maxn;i++)
		lowbit[i]=(i&-i);	
}

void update(int x,int v)
{
	for(int i=x;i<maxn;i+=lowbit[i])
		tree[i]+=v;
}

int query(int x)
{
	int ret(0);
	for(int i=x;i>0;i-=lowbit[i])
		ret+=tree[i];
	return ret;
	
}

void Cupdate(int x,int v)
{
	for(int i=x;i<maxn;i+=lowbit[i])
		cnt[i]+=v;
}

int Cquery(int x)
{
	int ret(0);
	for(int i=x;i>0;i-=lowbit[i])
		ret+=cnt[i];
	return ret;
}

int main()
{
	CalLowbit();
	int n,i,j,c;
	long long Less,More,Sum,ans;
	while(scanf("%d",&n)!=EOF)
	{
		memset(cnt,0,sizeof(cnt));
		memset(tree,0,sizeof(tree));
		for(i=0;i<n;i++)
			scanf("%d%d",&s[i].v,&s[i].pos);
		sort(s,s+n);
		ans=Sum=0;
		for(i=0;i<n;i++)
		{
			Less=query(s[i].pos);
			c=Cquery(s[i].pos);
			ans+=s[i].v*(c*s[i].pos-Less+(Sum-Less)-(i-c)*s[i].pos);
			update(s[i].pos,s[i].pos);
			Cupdate(s[i].pos,1);
			Sum+=s[i].pos;
		}
		printf("%lld\n",ans);
	}
	return 0;
}


对于hdu3015,先对D和H重新编号。后面的和poj1990差不多了。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxn = 100009;
int tree[maxn],cnt[maxn],lowbit[maxn],buf[maxn];

struct node
{
    int X,H;
    bool operator < (const node &t) const
    {
        return H>t.H;
    }
}s[maxn];

bool cmp1(node a,node b)
{
    return a.H<b.H;
}

bool cmp2(node a,node b)
{
    return a.X<b.X;
}

void Pre(int n)
{
    memset(tree,0,sizeof(tree[0])*(n+3));
    memset(cnt,0,sizeof(cnt[0])*(n+3));
    buf[0]=1;
    
    sort(s,s+n,cmp1);
    for(int i=1;i<n;i++)
    {
        if(s[i].H==s[i-1].H)
            buf[i]=buf[i-1];
        else
            buf[i]=i+1;
    }
    for(int i=0;i<n;i++)
        s[i].H=buf[i];
    
    sort(s,s+n,cmp2);
    for(int i=1;i<n;i++)
    {
        if(s[i].X==s[i-1].X)
            buf[i]=buf[i-1];
        else
            buf[i]=i+1;
    }
    for(int i=0;i<n;i++)
        s[i].X=buf[i];
        
    sort(s,s+n);
}

void CalLowbit()
{
    for(int i=1;i<maxn;i++)
        lowbit[i]=i&-i;
}

void update(int x,int v)
{
    for(int i=x;i<maxn;i+=lowbit[i])
        tree[i]+=v;
}

int query(int x)
{
    int ret(0);
    for(int i=x;i>0;i-=lowbit[i])
        ret+=tree[i];
    return ret;
}

void Cupdate(int x,int v)
{
    for(int i=x;i<maxn;i+=lowbit[i])
        cnt[i]+=v;
}

int Cquery(int x)
{
    int ret(0);
    for(int i=x;i>0;i-=lowbit[i])
        ret+=cnt[i];
    return ret;
}

int main()
{
    CalLowbit();
    int n,i,j,k,c;
    long long ans,Less,Sum;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<n;i++)
            scanf("%d%d",&s[i].X,&s[i].H);
        Pre(n);
        Sum=ans=0;
        for(i=0;i<n;i++)
        {
            Less=query(s[i].X);
            c=Cquery(s[i].X);
            ans+=s[i].H*(c*s[i].X-Less+Sum-Less-s[i].X*(i-c));
            Sum+=s[i].X;
            update(s[i].X,s[i].X);
            Cupdate(s[i].X,1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}


 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值