2 10 100 20 200 4 10 100 50 500 20 200 20 100
113
这道题和之前那题差不多,开两个一维树状数组b1,b2,分别维护x的位置和小于等于x位置的个数。先对x,h进行离散化,用r1,r2储存他们的名次,然后按h大小从大到小的顺序依次枚举就行了。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; struct node{ int x,h,r1,r2; }a[100006]; int b1[100006],b2[100006],n; bool cmp1(node a,node b){ return a.x<b.x; } bool cmp2(node a,node b){ return a.h<b.h; } int lowbit(int x){ return x&(-x); } void update1(int pos,int num) { while(pos<=n){ b1[pos]+=num;pos+=lowbit(pos); } } int getsum1(int pos) { int num=0; while(pos>0){ num+=b1[pos];pos-=lowbit(pos); } return num; } void update2(int pos,int num) { while(pos<=n){ b2[pos]+=num;pos+=lowbit(pos); } } int getsum2(int pos) { int num=0; while(pos>0){ num+=b2[pos];pos-=lowbit(pos); } return num; } int main() { int m,i,j,p,t1,t2; __int64 sum,sum1; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++){ scanf("%d%d",&a[i].x,&a[i].h); b1[i]=b2[i]=0; } sort(a+1,a+1+n,cmp1); a[1].r1=1;p=1; for(i=2;i<=n;i++){ if(a[i].x==a[p].x){ a[i].r1=a[p].r1; } else{ a[i].r1=i;p=i; } } sort(a+1,a+1+n,cmp2); a[1].r2=1;p=1; for(i=2;i<=n;i++){ if(a[i].h==a[p].h){ a[i].r2=a[p].r2; } else{ a[i].r2=i;p=i; } } sum=0;sum1=0; for(i=n;i>=1;i--){ t1=getsum1(a[i].r1); t2=getsum2(a[i].r1); sum+=a[i].r2*( t2*a[i].r1-t1 + sum1-t1-(n-i-t2)*a[i].r1 ); sum1+=a[i].r1; update1(a[i].r1,a[i].r1); update2(a[i].r1,1); //printf("%I64d\n",sum); } printf("%I64d\n",sum); } }
原文:http://blog.csdn.net/kirito_acmer/article/details/46446267