zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    斜率dp+cdq分治
    踢罐子 [几何+乱搞]
    [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]
    [xsy1129] flow [树链剖分和线段树一起优化网络流][我也不知道这是什么鬼标签]
    [CF666E] Forensic Examination [广义后缀自动机+线段树合并]
    省选算法学习-BSGS与exBSGS与二次剩余
    省选算法学习-回文自动机 && 回文树
    省选算法学习-后缀数组+后缀自动机+后缀树
    Password [分块]
    随机过程——泊松过程
  • 原文地址:https://www.cnblogs.com/jaszzz/p/12920316.html
Copyright © 2011-2022 走看看