MooFest
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 60000/30000K (Java/Other)
Problem Description
Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a social gathering of cows from around the world. MooFest involves a variety of events including haybale stacking, fence jumping, pin the tail on the farmer, and of course, mooing. When the cows all stand in line for a particular event, they moo so loudly that the roar is practically deafening. After participating in this event year after year, some of the cows have in fact lost a bit of their hearing.
Each cow i has an associated "hearing" threshold v(i) (in the range 1..20,000). If a cow moos to cow i, she must use a volume of at least v(i) times the distance between the two cows in order to be heard by cow i. If two cows i and j wish to converse, they must speak at a volume level equal to the distance between them times max(v(i),v(j)).
Suppose each of the N cows is standing in a straight line (each cow at some unique x coordinate in the range 1..20,000), and every pair of cows is carrying on a conversation using the smallest possible volume.
Compute the sum of all the volumes produced by all N(N-1)/2 pairs of mooing cows.
Each cow i has an associated "hearing" threshold v(i) (in the range 1..20,000). If a cow moos to cow i, she must use a volume of at least v(i) times the distance between the two cows in order to be heard by cow i. If two cows i and j wish to converse, they must speak at a volume level equal to the distance between them times max(v(i),v(j)).
Suppose each of the N cows is standing in a straight line (each cow at some unique x coordinate in the range 1..20,000), and every pair of cows is carrying on a conversation using the smallest possible volume.
Compute the sum of all the volumes produced by all N(N-1)/2 pairs of mooing cows.
Input
* Line 1: A single integer, N <br> <br>* Lines 2..N+1: Two integers: the volume threshold and x coordinate for a cow. Line 2 represents the first cow; line 3 represents the second cow; and so on. No two cows will stand at the same location. <br>
Output
* Line 1: A single line with a single integer that is the sum of all the volumes of the conversing cows. <br>
Sample Input
4 3 1 2 5 2 6 4 3
Sample Output
57
//题意:现在有很多头牛,每头牛有一个位置和一个耳聋程度,每头牛要和另外的所有牛说话(仅1次),每两头牛之间说话的声音必须是两者较大的那个耳聋度,要求距离*声音之和。
//思路:先把所有牛按耳聋程度排序(大->小),每次都选最聋的去和其他牛说话,这样,说话的声音就是这头牛的耳聋度(设为x)。设这头牛是第n个位置,总共有m个位置(输入的位置的最大值),每头牛的位置用dis1、dis2、...、dism表示,设该头牛前面共有num1头牛,后面共有num2头牛。
每头牛和另外所有牛说话的value=x*(dis(n+1)-dis(n)+dis(n+2)-dis(n)+...+dis(m)-dis(n))+x*(dis(n)-dis(1)+dis(n)-dis(2)+...+dis(n)-dis(n-1))=x*((dis(n+1)+dis(n+2)+...+dis(m))-num2*dis(n))+x*(num1*dis(n)-(dis(1)+dis(2)+...+dis(n-1)))
dis(n+1)+dis(n+2)+...+dis(m) 和dis(1)+dis(2)+...+dis(n-1)可以用一个树状数组解
num1、num2也可以用一个树状数组解
所以,这道题要用到2个树状数组!
(1)求num1、num2:
先设一个数组,大小为m。
有牛的位置设为1,没牛的位置设为0。套个树状数组模板(这里不解释了),num1=sum(n-1),num2=sum(m)-sum(n);每头牛结束后把它原来那个位置的值变成为0(即add(dis(n) , -1) ),因为1头牛只要跟其他牛说一次。
(2)求dis(n+1)+dis(n+2)+...+dis(m) 和dis(1)+dis(2)+...+dis(n-1):
再设一个数组,大小为m。
有牛的位置的值设为它的坐标,没牛的位置设为0。套个树状数组模板,dis(n+1)+dis(n+2)+...+dis(m) = sum(m)-sum(n);dis(1)+dis(2)+...+dis(n-1) = sum(n-1);每头牛结束后同样把它原来那个位置的值变成为0(即add(dis(n) , -dis(n)))。
最后用个ans,每次+=value就ok啦!上代码!
值可能非常大,尽量都用__int64,记得输入、输出的时候是%I64d ... 因为这个WA了2次— —!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAX = 20010;
typedef struct {
__int64 x;
__int64 num;
}Cow;
int n;
int maxx;
bool cmp(Cow p, Cow q)
{
return p.num > q.num;
}
__int64 lowbit(__int64 x)
{
return x&(-x);
}
void add(int k, __int64 x, __int64 c[])
{
while (k <= maxx)
{
c[k] += x;
k += lowbit(k);
}
}
__int64 sum(int x, __int64 c[])
{
__int64 sum = 0;
while (x > 0)
{
sum += c[x];
x -= lowbit(x);
}
return sum;
}
int main()
{
int i;
while (scanf("%d", &n) != EOF)
{
maxx = 0;
__int64 c[MAX];// 位置
__int64 a[MAX];// 0/1
Cow s[MAX];
memset(a, 0, sizeof(a));
memset(c, 0, sizeof(c));
for (i = 1; i <= n; i++)
{
scanf("%I64d%I64d", &s[i].num, &s[i].x);
if (s[i].x > maxx)
maxx = s[i].x;
}
for (i = 1; i <= n; i++)
{
add(s[i].x, 1, a);
add(s[i].x, s[i].x, c);
}
sort(s + 1, s + n + 1, cmp);
__int64 ans = 0;
for (i = 1; i <= n; i++)
{
//跟后面的牛说话
__int64 temp1 = s[i].num*((sum(maxx, c) - sum(s[i].x, c)) - (sum(maxx, a) - sum(s[i].x, a))*s[i].x);
//跟前面的牛说话
__int64 temp2 = s[i].num*((sum(s[i].x - 1, a))*s[i].x - (sum(s[i].x - 1, c)));
add(s[i].x, -1, a);
add(s[i].x, -s[i].x, c);
ans += (temp1 + temp2);
}
printf("%I64d\n", ans);
}
return 0;
}