POJ1990 - MooFest
题目大意
给定N对二元组(x1,y1),(x2,y2),(x3,y3)…(xn,yn).每两个二元组之间(假设分别为i和j,i!=j)将会产生一个值ans(i,j)=max(xi,xj)*|yi-yj|,计算出sigma(ans(i,j))(1<=i,j<=n,i!=j)
题解
我们可以先对x值按升序排序,之后就是用两个树状数组进行维护了,公式推导过程不知道怎么讲。。。直接看代码好了。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 20005 using namespace std; typedef struct { int v; int x; } NODE; NODE a[MAXN]; int n; long long c[MAXN],b[MAXN]; int lowbit(int x) { return x&-x; } int sum(long long p[],int x) { int ret=0; while(x>0) { ret+=p[x]; x-=lowbit(x); } return ret; } void add(long long p[],int x,int d) { while(x<=MAXN) { p[x]+=d; x+=lowbit(x); } } bool cmp(NODE a,NODE b) { return a.v<b.v; } int main(void) { long long ans=0,total=0,cnt,sums; int i; scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d%d",&a[i].v,&a[i].x); sort(a+1,a+n+1,cmp); memset(c,0,sizeof(c)); memset(b,0,sizeof(b)); for(i=1; i<=n; i++) { cnt=sum(b,a[i].x); sums=sum(c,a[i].x); ans+=a[i].v*(total-2*cnt+(2*sums-i+1)*a[i].x); add(b,a[i].x,a[i].x); add(c,a[i].x,1); total+=a[i].x; } cout<<ans<<endl; return 0; }