zoukankan      html  css  js  c++  java
  • poj 1990 MooFest

    点击打开poj 1990

    思路: 树状数组

    分析:

    1 题目给定n头牛的听力v[i]. 现在规定两头你i和j如果要进行交流的话那么消耗的能量就是dis(i,j)*max(v[i].v[j]),现在问n头牛总共的n*(n-1)*2种方式消耗的总的能量

    2 题目要求的是所有的牛的交流方式的总的消耗能量

       看这个样例

       3 1

       2 5

       2 6

       4 3

       那么所有的区间为[1.3],[1,5],[1,6],[3,5],[3,6],[5,6]

       那么总和为4*dis[1.3]+3*dis[1,5]+3*dis[1,6]+4*dis[3,5]+4*dis[3,6]+2*dis[5,6] = 4*(dis[1.3]+dis[3,5]+dis[3,6])+3*(dis[1,5]+dis[1,6])+2*(dis[5,6]);

       那么题目要求的ans = (v[i]*(所有比v[i]小的牛的坐标的总和))


    3 那么我们来分解这个式子,我们对点按照音量的值从小到大排完序之后

       那么对于任一的一点i,i之前的牛的音量值肯定小于v[i],但是坐标的值可能比x[i]大也可能比x[i]小,因此我们应该分成两部分来考虑,就是坐标是i的左边和右边


       首先考虑左边的情况,假设左边比小于等于v[i]的牛有三头坐标分别为a b c,那么左边的值就是v[i]*(x[i]-a)+v[i]*(x[i]-b)+v[i]*(x[i]-c) => v[i]*(3*x[i]-(a+b+c))

       那么我们假设左边小于v[i]的牛有countLeft头,总的坐标为totalLeft,那么左边的值为v[i]*(countLeft*x[i]-totalLeft);


       接下来考虑右边的情况,由于我们已经按照v的值排序,那么我们能够很好的计算出小于等于v[i]的音量值的总的坐标之后,我们设为totalDis,那么根据左边求出的小于

       等于v[i]的个数为countLeft,那么右边的个数为i-countLeft,那么同理右边的坐标之和为totalDis-totalLeft , 那么右边的值为v[i]*(totalDis-totalLeft-(i-countLeft)*x[i]);


       那么对于排序后的第i头牛来说比它小的音量的牛的值为v[i]*(countLeft*x[i]-totalLeft)+v[i]*(totalDis-totalLeft-(i-countLeft)*x[i]);


    4 我们已经知道了公式,现在我们只要去求countLeft和totalLeft即可,由于我们已经按照v的值排序, 那么我们只要对坐标建立两个树状数组即可。一个用来存储个数,一个用来存储坐标之和,那么对于第i头牛来说我们就能够在O(logn)的时间内求出countLeft和totalLeft


    代码:

    /***********************************************
    * By: chenguolin                               * 
    * Date: 2013-08-19                             *
    * Address: http://blog.csdn.net/chenguolinblog *
    ***********************************************/
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long int64;
    const int MAXN = 20010;
    
    struct Node{
        int x;
        int v;
        bool operator<(const Node& s)const{
            return v < s.v; 
        }
    };
    Node node[MAXN];
    int n;
    int treeCount[MAXN];
    int treeDis[MAXN];
    
    int lowbit(int x){
        return x&(-x);
    }
    
    int64 getSum(int x , int *arr){
        int64 sum = 0;
        while(x){
             sum += arr[x];
             x -= lowbit(x);
        }
        return sum;
    }
    
    void add(int x , int val , int *arr){
        while(x < MAXN){
             arr[x] += val; 
             x += lowbit(x); 
        }
    }
    
    int64 solve(){
        int64 ans = 0;
        int64 totalDis = 0;
        memset(treeCount , 0 , sizeof(treeCount));
        memset(treeDis , 0 , sizeof(treeDis));
        sort(node , node+n);
    
        for(int i = 0 ; i < n ; i++){
            int64 count = getSum(node[i].x , treeCount); 
            int64 dis = getSum(node[i].x , treeDis);
            // left
            ans += node[i].v*(count*node[i].x-dis);
            // right
            ans += node[i].v*((totalDis-dis-(i-count)*node[i].x));
            // update 
            totalDis += node[i].x;
            add(node[i].x , 1 , treeCount);
            add(node[i].x , node[i].x , treeDis);
        }
        return ans;
    }
    
    int main(){
        while(scanf("%d" , &n) != EOF){
             for(int i = 0 ; i < n ; i++) 
                 scanf("%d%d" , &node[i].v , &node[i].x);
             printf("%lld
    " , solve());
        }
        return 0;
    }
    
    


  • 相关阅读:
    Ghost博客安装
    PHP变量作用域
    ssh文件传输命令:sz与rz命令
    excel怎么固定第一行
    memcache和redis区别
    Memcache分布式部署方案
    Memcache服务器端参数说明
    Memcache基础教程
    在Windows下安装Memcached
    MySQL体系结构和存储引擎概述
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3268600.html
Copyright © 2011-2022 走看看