Disharmony Trees (好一个树状数组+离散化)

Posted 胖川怎么可能不胖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Disharmony Trees (好一个树状数组+离散化)相关的知识,希望对你有一定的参考价值。

One day Sophia finds a very big square. There are n trees in the square. They are all so tall. Sophia is very interesting in them.


She finds that trees maybe disharmony and the Disharmony Value between two trees is associated with two value called FAR and SHORT.

The FAR is defined as the following:If we rank all these trees according to their X Coordinates in ascending order.The tree with smallest X Coordinate is ranked 1th.The trees with the same X Coordinates are ranked the same. For example,if there are 5 tree with X Coordinates 3,3,1,3,4. Then their ranks may be 2,2,1,2,5. The FAR of two trees with X Coordinate ranks D1 and D2 is defined as F = abs(D1-D2).

The SHORT is defined similar to the FAR. If we rank all these trees according to their heights in ascending order,the tree with shortest height is ranked 1th.The trees with the same heights are ranked the same. For example, if there are 5 tree with heights 4,1,9,7,4. Then their ranks may be 2,1,5,4,2. The SHORT of two trees with height ranks H1 and H2 is defined as S=min(H1,H2).

Two tree’s Disharmony Value is defined as F*S. So from the definition above we can see that, if two trees’s FAR is larger , the Disharmony Value is bigger. And the Disharmony value is also associated with the shorter one of the two trees. 

Now give you every tree’s X Coordinate and their height , Please tell Sophia the sum of every two trees’s Disharmony value among all trees.

Input

There are several test cases in the input

For each test case, the first line contain one integer N (2 <= N <= 100,000) N represents the number of trees.

Then following N lines, each line contain two integers : X, H (0 < X,H <=1,000,000,000 ), indicating the tree is located in Coordinates X and its height is H.

Output

For each test case output the sum of every two trees’s Disharmony value among all trees. The answer is within signed 64-bit integer.

Sample

InputcopyOutputcopy
 
2 
10 100 
20 200 
4 
10 100
50 500
20 200 
20 100 
 
1 
13

翻译:

        FAR的定义如下:如果我们根据这些树的X坐标从大到小进行排序,X坐标最小的树排在第1位,X坐标相同的树排在一起。例如,如果有5棵X坐标为3、3、1、3、4的树。那么他们的等级可能是2,2,1,2,5。X坐标等级为D1和D2的两棵树的FAR被定义为F=abs(D1-D2)。

SHORT的定义与FAR相似。如果我们根据这些树的高度从高到低排序,高度最短的树排在第1位,高度相同的树排在一起。例如,如果有5棵树,高度为4,1,9,7,4。那么他们的排名可能是2,1,5,4,2。高度为H1和H2的两棵树的SHORT被定义为S=min(H1,H2)。

两棵树的不和谐值被定义为F*S。因此,从上面的定义我们可以看出,如果两棵树的FAR越大,Disharmony值就越大。而且不和谐值也与两棵树中较短的那棵有关。

现在给你每棵树的X坐标和它们的高度,请告诉Sophia所有树中每两棵树的不和谐值之和。

题目大意:

        将树按照x坐标和高度分别从大到小排序。小的F从1开始,如果俩颗树的x坐标相同,那么等级相同。类似于x坐标为3,1,3,3,5 。那么他的F就是2,1,2,2,5.高度S同样如此排序,然后求俩俩之间F*S的和:v=min(h1,h2)*abs(x1,x2)

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<stack>
#include<string>
#include<algorithm>
//#include<unordered_map>
#include<map>
#include<cstring>
//#include <unordered_set>
#include<queue>
#include<set>
#include<stdlib.h>
#define dbug cout<<"hear!"<<endl;
#define rep(a,b,c) for(ll a=b;i<=c;a++)
#define per(a,b,c) for(ll a=b;i>=c;a--)
#define no cout<<"NO"<<endl;
#define yes cout<<"YES"<<endl;
#define endl "\\n"
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//priority_queue<int,vector<int>,greater<int> >q;
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> PII;
typedef pair<long double,long double> PDD;
const int N = 1e5 + 5;
const int  INF = 0x3f3f3f3f;
//const ll LINF=LLONG_MAX;
// ll gcdd(ll a, ll b)
// 
//       while(b^=a^=b^=a%=b);    
//       return a;
// 
// void add(ll a,ll w)
// 
//   noda[++idx].b=w;
//   noda[idx].ne=h[a];
//   h[a]=idx;
// 
ll h[N],idx;
const ll mod =1000000007;
ll  t, n,a,b,c,d, m, x,y, k, cnt, ans, ant, sum,q,p,num;
ll arr[N],brr[N], crr[N];
ll book[N];
struct node

  ll x,h;
  ll xx,hh;
noda[N];
bool cmpx(node a,node b)

  return a.x<b.x;

bool cmph(node a,node b)

  return a.h<b.h;

bool cmphh(node a,node b)

  return a.hh>b.hh;

ll lowbit(ll x)

  return x&(-x);

void update(ll c[],ll x,ll w)

  for(ll i=x;i<=num+1;i+=lowbit(i))c[i]+=w;

ll getsum(ll c[],ll x)

  sum=0;
  for(ll i=x;i;i-=lowbit(i))sum+=c[i];
  return sum;

int main()

  IOS;
  while(cin>>n)
  
    num=0;
    rep(i,1,n)
    
      cin>>noda[i].x>>noda[i].h;
      arr[i]=brr[i]=0;
    
    sort(noda+1,noda+1+n,cmpx);//按照x坐标进行排序
    noda[1].xx=1;//第一个位置离散化为1;
    rep(i,2,n)
    
      if(noda[i].x==noda[i-1].x)
      
        noda[i].xx=noda[i-1].xx;//如果相同那么,其等级是一样的
        num++;
      else 
      
        noda[i].xx=i;//如果不相同,那么按照题目意思是不去重重的离散化,所以直接变成i;
        num++;
      
    
    sort(noda+1,noda+1+n,cmph);//按照h排序;
    noda[1].hh=1;
    rep(i,2,n)
    
      if(noda[i].h==noda[i-1].h)
      
        noda[i].hh=noda[i-1].hh;
      else
        noda[i].hh=i;
      
    
    sort(noda+1,noda+1+n,cmphh);//按照hh再进行一次排序这样就可以避免用min函数;
    ans=0;
    rep(i,1,n)
    
      a=getsum(arr,noda[i].xx);//得到xx之前的个数
      b=getsum(brr,noda[i].xx);//得到xx之前的个数和
       cnt=getsum(brr,n);//得到综合,算区间
      ans+=noda[i].hh*((a*noda[i].xx -b)+(cnt-b)-(i-a-1)*noda[i].xx);//这样计算可以规避出现负数情况。
      update(arr,noda[i].xx,1);
      update(brr,noda[i].xx,noda[i].xx);
    
    cout<<ans<<endl;
  


 

HDU 3015 Disharmony Trees(树状数组)

题意:给你n棵树,每棵树上有两个权值X H

对于X离散化 :3 7 1 5 3 6 -> 2 6 1 4 2 5,对于H一样

然后F = abs(X1-X2)   S=min(H1,H2)

求出每一对F*S的总和 

 

可以看到一边是求每个数与其他数的最小值,一边是求每个数与其他数的差距。因此我们可以排序一边,处理另一边。

我们排序H,因为这样对于固定一个Xi Hi,从小到大每次都是Hi去乘以Xi与剩下的所有X的差的总和。

这样我们就可以使用树状数组维护两个值:每个位置值的个数,每个位置值的总大小,接着细心点处理就好了

 

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=100010;
struct node
{
    int sub,minx;
} tree[Max];
int n;
bool cmpt(struct node p1,struct node p2)
{
    return p1.sub<p2.sub;
}
bool cmp(struct node p1,struct node p2)
{
    return p1.minx<p2.minx;//按照最值排序才能固定一个值
}
int lowbit(int x)
{
    return x&(-x);
}
void Add(ll *bit,int x,ll y)
{
    while(x<=n)
    {
        bit[x]+=y;
        x+=lowbit(x);
    }
    return;
}
ll Sum(ll *bit,int x)
{
    ll sum=0ll;
    while(x)
    {
        sum+=bit[x];
        x-=lowbit(x);
    }
    return sum;
}
ll bit[Max],bit2[Max];//存个数 存大小
ll Solve()
{
    ll ans=0ll;
    memset(bit,0ll,sizeof(bit));
    memset(bit2,0ll,sizeof(bit2));
    for(int i=0;i<n;++i)
    {
        Add(bit2,tree[i].sub,(ll)tree[i].sub);
        Add(bit,tree[i].sub,1ll);
    }
    for(int i=0;i<n;++i)
    {
        Add(bit2,tree[i].sub,(ll)-tree[i].sub);
        Add(bit,tree[i].sub,-1ll);
       // printf("%d\n",tree[i].sub);
        ans+=(ll)tree[i].minx*(
        Sum(bit2,n)-Sum(bit2,tree[i].sub)-(ll)tree[i].sub*(Sum(bit,n)-Sum(bit,tree[i].sub))+
        (ll)tree[i].sub*Sum(bit,tree[i].sub)-Sum(bit2,tree[i].sub));//关键
        //printf("%I64d %I64d\n",ans,Sum(bit2,n)-Sum(bit,n)*tree[i].sub);
    }
    return ans;
}
int main()
{
    int tmp;
    while(~scanf("%d",&n))
    {
        for(int i=0; i<n; ++i)
            scanf("%d %d",&tree[i].sub,&tree[i].minx);
        sort(tree,tree+n,cmpt);//离散化
        tree[n].sub=tree[n].minx=-1;
        tmp=1;
        for(int i=0; i<n; ++i)
        {
            if(tree[i].sub!=tree[i+1].sub)
            {
                tree[i].sub=tmp;
                tmp=i+2;
            }
            else
            {
                tree[i].sub=tmp;
            }
        }
        sort(tree,tree+n,cmp);
        tmp=1;
                for(int i=0; i<n; ++i)
        {
            if(tree[i].minx!=tree[i+1].minx)
            {
                tree[i].minx=tmp;
                tmp=i+2;
            }
            else
            {
                tree[i].minx=tmp;
            }
        }
      //  for(int i=0;i<n;++i)
        //    printf("%d %d\n",tree[i].sub,tree[i].minx);
        printf("%I64d\n",Solve());
    }
    return 0;
}

 

以上是关于Disharmony Trees (好一个树状数组+离散化)的主要内容,如果未能解决你的问题,请参考以下文章

hdu-3015 Disharmony Trees---离散化+两个树状数组

hdu3015 Disharmony Trees

Disharmony Trees

POJ-2029 Get Many Persimmon Trees---二维树状数组+枚举

POJ 2029 Get Many Persimmon Trees (二维树状数组)

Get Many Persimmon Trees_枚举&&二维树状数组