首页 > 其他分享 >P5094 [USACO04OPEN] MooFest G 加强版

P5094 [USACO04OPEN] MooFest G 加强版

时间:2024-04-15 12:33:06浏览次数:31  
标签:cnt ll cal lt while MooFest sum USACO04OPEN P5094

原题链接

题解

\(O(n^2)\) 不可能,所以考虑线性,将奶牛按下标排序,顺序遍历,对于 \(i\) 而言,它的贡献等于 \(\sum_{j\lt i\ ,\ v[j]\leqslant v[i]}{dis(i,j)·v[i]}\) ,等于 \(v[i]·((\sum_{j\lt i\ ,\ v[j]\leqslant v[i]}{1})·x[i]-\sum_{j\lt i\ ,\ v[j]\leqslant v[i]}{x[j]})\)
逆序遍历贡献为 \(v[i]·((\sum_{j\gt i\ ,\ v[j]\lt v[i]}{1})·x[i]-\sum_{j\gt i\ ,\ v[j]\lt v[i]}{x[j]})\)

把 \(v\) 看作x轴 , 等价于求 小于v的个数 和 小于v的dis和 ,用两个树状数组解决

code

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
#define ll long long
inline void read(ll &x) {
    x = 0;
    ll flag = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-')flag = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    x *= flag;
}

inline void write(ll x)
{
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
ll n;
struct node
{
    ll v,x,haxi;
} cow[50005];
ll cnt[50005]={0}, sum[50005]={0};

ll query_cnt(ll x)
{
    ll cal=0;
    while(x)
    {
        cal+=cnt[x];
        x-=lowbit(x);
    }
    return cal;
}

ll query_sum(ll x)
{
    ll cal=0;
    while(x)
    {
        cal+=sum[x];
        x-=lowbit(x);
    }
    return cal;
}

void update_cnt(ll x)
{
    while(x<=50005)//Because x is small, discretization is not necessary.
    {
        cnt[x]++;
        x+=lowbit(x);
    }
}

void update_sum(ll x, ll val)
{
    while(x<=50005)
    {
        sum[x]+=val;
        x+=lowbit(x);
    }
}

bool cmp(node a, node b)
{
    return a.x<b.x;
}

int main()
{
    ll n;
    read(n);
    for(ll i=1; i<=n; i++)
    {
        read(cow[i].v);
        read(cow[i].x);
    }

    ll ans=0;

    sort(cow+1, cow+1+n, cmp);
    for(ll i=1; i<=n; i++)
    {
        ll index=cow[i].v;
        ans+=cow[i].v*(query_cnt(index)*cow[i].x-query_sum(index));
        update_cnt(index);
        update_sum(index, cow[i].x);
    }

    memset(cnt, 0, sizeof cnt);
    memset(sum, 0, sizeof sum);

    for(ll i=n; i>=1; i--)
    {
        ll index=cow[i].v;
        ans+=cow[i].v*(query_sum(index-1)-query_cnt(index-1)*cow[i].x);
        update_cnt(index);
        update_sum(index, cow[i].x);
    }

    write(ans);
    return 0;
}

标签:cnt,ll,cal,lt,while,MooFest,sum,USACO04OPEN,P5094
From: https://www.cnblogs.com/pure4knowledge/p/18135707

相关文章

  • P2345 [USACO04OPEN] MooFest G
    按\(v\)从小到大排序,这样可以转化为\(v_j\times|x_i-x_j|(i<j)\)。CDQ分治,返回时按照\(x\)从小到大排序。考虑如何计算前一段区间对后一段区间的贡献。假设前一段区间当前扫到\(i\),后一段区间当前扫到\(j\)。每次拿出最小的计算贡献。如果\(x_i\leqx_j\),则贡献为\(\s......
  • MooFest G(USACO04OPEN)
    ​​传送门​​这题可以采用分治的方法,类似于归并排序的思路。其核心问题在于,我们怎么化简左右结合的步骤?如果我们只是单纯的分别计算左右两两的音量,那就是假的分治,实则是......