• POJ1990:MooFest——题解


    http://poj.org/problem?id=1990

    题目大意:定义一对在树轴上的点,每对点产生的值为两点权值最大值*两点距离,求点对值和。

    显然n*n复杂度不行,我们需要用树状数组维护两个东西。

    对于某位置,一个是它和它前置位坐标和,一个是它和它前置位点的个数。

    我们按照点i权值v从小到大排序添加,这样对于我们在树状数组里的点,我们一定是要乘当前的点的v,剩下的就是乘距离了。

    对于坐标比它小的点的个数为num,坐标和为x,我们有答案num*x[i]-x。

    同理对于坐标比它大的点也可以求,化简得到:

    ans+=c[i].v*(querydis(N)-2*querydis(c[i].x)-(i-1-2*querynum(c[i].x))*c[i].x);

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    inline ll read(){
        int X=0,w=0; char ch=0;
        while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
        while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    const int N=20001;
    struct cow{
        int v;
        int x;
    }c[N];
    bool cmp(cow a,cow b){
        return a.v<b.v;
    }
    int n,m;
    ll num[N],dis[N];
    inline int lowbit(int t){return t&(-t);}
    void add(int x,int y1,int y2){
        for(int i=x;i<=N;i+=lowbit(i)){num[i]+=y1;dis[i]+=y2;}
        return;
    }
    ll querydis(int x){
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i))res+=dis[i];
        return res;
    }
    ll querynum(int x){
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i))res+=num[i];
        return res;
    }
    int main(){
        n=read();
        for(int i=1;i<=n;i++){
        c[i].v=read();
        c[i].x=read();
        }
        sort(c+1,c+n+1,cmp);
        ll ans=0;
        for(int i=1;i<=n;i++){
        ans+=c[i].v*(querydis(N)-2*querydis(c[i].x)-(i-1-2*querynum(c[i].x))*c[i].x);
        add(c[i].x,1,c[i].x);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Redis扩展功能
    Redis持久化
    redis-通讯协议及事件处理机制
    Redis-数据类型与底层数据结构
    分布式集群架构场景化解决方案
    MySQL-运维和第三方工具
    缓存原理&设计
    MySQL性能优化
    MySQL高级-日志常用的工具等等
    Mysql高级——优化
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7886877.html
Copyright © 2020-2023  润新知