HDU3015 - Disharmony Trees
题目大意
和POJ1990是一样的,只是把max改成min了。。。
给定N对二元组(x1,y1),(x2,y2),(x3,y3)…(xn,yn).每两个二元组之间(假设分别为i和j,i!=j)将会产生一个值ans(i,j)=min(xi,xj)*|yi-yj|,计算出sigma(ans(i,j))(1<=i,j<=n,i!=j)
题解
需要对x,y进行离散,然后把y值按降序排序,之后的做法和POJ3015完全是一样的。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 100005 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 cmp1(NODE a,NODE b) { return a.x<b.x; } bool cmp2(NODE a,NODE b) { return a.v>b.v; } int main(void) { long long ans,total,cnt,sums; int pre,prev; int i; while(scanf("%d",&n)!=EOF) { ans=0; total=0; for(i=1; i<=n; i++) scanf("%d%d",&a[i].x,&a[i].v); sort(a+1,a+n+1,cmp1); pre=-1; prev=0; for(i=1; i<=n; i++) if(pre!=a[i].x) { pre=a[i].x; a[i].x=i; prev=i; } else a[i].x=prev; sort(a+1,a+n+1,cmp2); pre=-1; prev=0; for(i=n; i>=1; i--) if(pre!=a[i].v) { pre=a[i].v; a[i].v=n-i+1; prev=n-i+1; } else a[i].v=prev; 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; }