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

原创 2015年07月11日 09:03:52

题目: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;
}




版权声明:转吧。

相关文章推荐

hdu3015 Disharmony Trees(树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3015 题意:在路边有一行树,给出它们的坐标和高度,先按X坐标排序。记录排名,记为rankx,再按它们...

hdu 3015 Disharmony Trees(树状数组)

Disharmony TreesProblem DescriptionOne day Sophia finds a very big square. There are n trees in the ...

HDU 3015 Disharmony Trees 树状数组

来源:http://acm.hdu.edu.cn/showproblem.php?pid=3015 题意:有一些树,这些树的高度和位置给出。现在高度和位置都按从小到大排序,对应一个新的rank,任意...

POJ 1990 MooFest(树状数组)#by zh

这道题是给出直线上的一些点,每个点都有一个权值,现在要求记录每两个点之间的花费之和是多少,两点之间的花费是指这两个点权值的最大值乘以两点间距离。时间就给了一秒O(n^2)的算法肯定是不行的能优化的地方...

poj1990MooFest(树状数组)

拿到题我们只需要考虑v比这个数小的就可以了,ans = Σv [i] * 比这个数小的点到这个数的距离之和。 那么这个距离之和怎么求呢?对于第 i 个数来说, 设 front [ i ]  表示v...

POJ 1990 MooFest(树状数组)

题目链接: 点击打开链接 该题是一道很巧妙的树状数组的应用,一开始初学ACM的时候曾经看别人题解做过,然而一丝作用也没有,完全没有理解该题,以至于现在见到和没做过一样。 个人认为学习树状数组还...

【树状数组--思维】poj1990 MooFest

MooFest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7910   Accept...

POJ 1990 MooFest 树状数组

题目大意:Farmer John又来恶心我们了!这次他带来了一些牛,这些牛排成一列,他们的位置给出,每一个牛有一个音调。这些牛每两只牛之间都要互相交流,但是交流的时候会有一些花费,i,j两只牛的cos...

POJ - 1990 MooFest解题报告(树状数组+离线处理)

题目大意:有一排acm大牛(20,000),告诉你他们每个人的听力水平和所在位置坐标,并且他们每个人之间交流都需要的声音大小为:他们之间的距离乘他们两个人听力水平的较大值。现在问你每一对牛都交流一次,...

poj 1990 MooFest (树状数组)

题目:http://poj.org/problem?id=1990 思路见代码: #include #include #include #include using namespace std...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)