• POJ 1990 MooFest


    题目

    题意:有m头牛,每头牛有两个值,v和x,两两之间有一个值,设v分别为v1,v2,x为x1,x2,则它们之间的值为abs(x1-x2) * Max(v1,v2),求所有m*(m-1)/2对牛之间值的总和。

    思路:咋看第一眼都是暴力这个优秀算法,不过暴力肯定是不行的,所以要树状数组优化

          我们可以先将牛以V排序,这时只需要考虑每一个 i 左右的X的情况

    // #include<bits/stdc++.h>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring> // for memset
    #include <vector> // push_back() // vector<int>().swap(v);
    #include <set> //multiset set<int,greater<int>> //big->small
    #include <map>
    #include <stack> // top()
    #include <queue> // front() // priority_queue<T,vector<T>,greater<T> >
    #include <cmath> // auto &Name : STLName  Name.
    #include <utility>
    #include <sstream>
    #include <string> // __builtin_popcount (ans); // 获取某个数二进制位1的个数
    #include <cstdlib> // rand()
    
    #define IOS ios_base::sync_with_stdio(0); cin.tie(0)
    using namespace std;
    typedef long long ll;
    
    int lowbit(int x){ return x&(-x);}
    
    const int maxn = 20010;
    
    struct Node
    {
        int x,v;
        bool operator< (const Node& s)const{return v<s.v;}
    }node[maxn];
    
    int n;
    int treeCount[maxn];
    int treeDis[maxn];
    
    ll sum(int x,int *t)
    {
        ll ans=0;
        while(x)
        {
            ans+=t[x];
            x-=lowbit(x);
        }
        return ans;
    }
    
    void add(int x,int v,int *t)
    {
        while(x<maxn)
        {
            t[x]+=v;
            x+=lowbit(x);
        }
    }
    
    ll solve()
    {
        ll ans=0;
        ll totalDis=0;
        memset(treeCount , 0 , sizeof(treeCount));
        memset(treeDis , 0 , sizeof(treeDis));
        sort(node,node+n);
    
        for(int i=0;i<n;i++)
        {
            ll count=sum(node[i].x,treeCount);
            ll dis=sum(node[i].x,treeDis);
    
            ans+=node[i].v*(count*node[i].x-dis);
            ans+=node[i].v*((totalDis-dis-(i-count)*node[i].x));
    
            totalDis += node[i].x;
            add(node[i].x , 1 , treeCount);
            add(node[i].x , node[i].x , treeDis);
        }
        return ans;
    }
    
    int main(void)
    {
        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;
    }
    

      

  • 相关阅读:
    正则匹配
    去除数组、对象某个元素
    换行
    a标签问题
    vue的坑
    宽度100%-20px ,css样式设置超出部分...
    搜狗密码框自带小键盘问题
    阻止button刷新页面
    Java IO流经典练习题
    Java中统计字符串中各个字符出现的次数
  • 原文地址:https://www.cnblogs.com/jaszzz/p/12920316.html
Copyright © 2020-2023  润新知