• POJ 1990 MooFest | 树状数组


    题面:

    给出一群牛,每个牛牛有一个坐标和val,每两对牛牛之间的w被定义为

    dis(x[i],x[j])*max(val[i],val[j])

    求w的和


    题解:

    我们如果按val排序,对于i来说,和他构成的权值乘的是val[i]的显然是1~i-1的牛牛

    设有a个牛在他前面,b个牛在他后面

    公式变成val[i]*(a*x[i]-前面牛的距离和+后面牛的距离和-b*x[i])

    接下来考虑维护一下他和其他牛牛的距离,可以用树状数组记录一下,给每个坐标赋一个大小为坐标的权值

    这样用树状数组就维护可以这个点之前有多少dis,这个点之后有多少dis,
    顺便维护一下前后多少牛即可

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define N 20100
     5 typedef long long ll;
     6 using namespace std;
     7 struct cow
     8 {
     9     ll x,val;
    10     bool operator < (const cow &a) const
    11     {
    12         return val<a.val;
    13     }
    14 }c[N];
    15 ll n,maxx,ans;
    16 struct BIT
    17 {
    18     ll t[N],lim;
    19     void modify(ll x,ll k)
    20     {
    21         while (x<=lim)
    22         t[x]+=k,x+=x&-x;
    23     }
    24     ll query(ll x)
    25     {
    26         ll ret=0;
    27         while (x>0)
    28         ret+=t[x],x-=x&-x;
    29         return ret;
    30     }
    31 }dis,cnt;
    32 int main()
    33 {
    34     scanf("%lld",&n);
    35     for (int i=1;i<=n;i++)
    36     scanf("%lld%lld",&c[i].val,&c[i].x),maxx=max(maxx,c[i].x);
    37     sort(c+1,c+1+n);
    38     dis.lim=maxx,cnt.lim=maxx;
    39     for (int i=1;i<=n;i++)
    40     {
    41     ll tmp=cnt.query(c[i].x);
    42     ans+=c[i].val*(tmp*c[i].x-dis.query(c[i].x));
    43     tmp=cnt.query(maxx)-cnt.query(c[i].x);
    44     ans+=c[i].val*(dis.query(maxx)-dis.query(c[i].x)-tmp*c[i].x);
    45     cnt.modify(c[i].x,1);
    46     dis.modify(c[i].x,c[i].x);
    47     }
    48     printf("%lld",ans);
    49     return 0;
    50 }
  • 相关阅读:
    POJ 2349 Arctic Network
    OpenJudge 东方14ACM小组 / 20170123 06:Challenge 3
    OpenJudge 东方14ACM小组 / 20170123 02 岛屿
    Best Coder Lotus and Characters
    洛谷 P 1164 小A点菜
    楼房
    虫食算
    斗地主
    国王游戏
    最优贸易
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7879994.html
Copyright © 2020-2023  润新知