本质上是一道统计点对之间贡献的题目。

将每个奶牛看作一个点对\((v_i,x_i)\),\(i\)能对\(j\)产生贡献,当且仅当下面条件其一成立:

  • \(v_i\le v_j,x_i>x_j\),此时的贡献为\((x_i-x_j)\times v_j\)。
  • \(v_i\le v_j,x_i<x_j\),此时的贡献为\((x_j-x_i)\times v_j\)。

大体思路是这样,有不同的实现方法。

Sol #1 树状数组

根据上面的分析,我们可以将点对按\(v\)从小到大排序,依次遍历,将\(x\)丢进树状数组。

\(i\)之前的\(x\)被丢进树状数组后,统计对\(i\)的贡献。

  • 先查树状数组中\(x\in [1,x_i-1]\)的\(x\)之和,记为\(s\),这样的\(x\)的个数记为\(c\),对答案的贡献即为\((c\times x_i-s)\times v_i\);
  • 再查\([x_i+1,+\infty]\),对答案的贡献为\((s-c\times x)\times v_i\)。

时间复杂度\(O(n\log V)\),其中\(V\)是值域。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e4+10,Ve=5e4,V=Ve+10;//e=exact
int n,ans;
inline int lb(int x){return x&-x;}
struct BIT{
int s[V],c[V];
void chp(int x,int v){for(;x<=Ve;x+=lb(x)) s[x]+=v,c[x]++;}
void qry(int x,int y,int& _s,int& _c){
_s=_c=0,x--;
for(;y;y-=lb(y)) _s+=s[y],_c+=c[y];
for(;x;x-=lb(x)) _s-=s[x],_c-=c[x];
}
}bit;
struct Node{int a,v;}a[N];
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].v>>a[i].a;
sort(a+1,a+1+n,[](Node a,Node b){return a.v<b.v;});
for(int i=1,s,c;i<=n;i++){
bit.qry(1,a[i].a-1,s,c);
ans+=a[i].v*(c*a[i].a-s);
bit.qry(a[i].a+1,Ve,s,c);
ans+=a[i].v*(s-c*a[i].a);
bit.chp(a[i].a,a[i].a);
}
cout<<ans<<"\n";
return 0;
}

Sol #2 CDQ分治

统计点对贡献,当然少不了CDQ分治~

不妨对\(v\)分治,按照\(x\)合并。

具体来说,将\(v\)从小到大排序,然后从\([1,n]\)开始不断分成左右两个区间递归处理,每个子问题只计算跨区间的贡献。这也是CDQ分治的核心思想。

递归处理完左右子问题后,将左右区间内部按\(x\)从小到大排序,尽管\(v\)的顺序已经被打乱,但是由于是区间内部的排序,所以左区间的\(v\)值始终\(\le\)右区间的\(v\)值。仅需关心\(x\)之间的关系。

我们用双指针\(i,j\)分别指向左右区间,\(j\)每次移动之前,\(i\)都移动到最大的位置使得\(x_i<x_j\)。这样\([l,i]\)的点对满足第二个条件,\([i+1,mid]\)的点对满足第一个条件。对照式子统计即可。

按\(x\)排序的过程如果写成sort会是\(O(n\log^2 n)\)的,可以在递归的同时进行归并排序,这样就可以降到\(O(n\log n)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e4+10;
int n,ans;
struct Node{int a,v;}a[N],t[N];
int cdq(int l,int r){//返回值为[l,r]内a的和
if(l==r) return a[l].a;
int mid=(l+r)>>1,i,j,k,s=0,sl=cdq(l,mid),sr=cdq(mid+1,r);
for(i=k=l,j=mid+1;j<=r;j++){
while(i<=mid&&a[i].a<a[j].a) s+=a[i].a,t[k++]=a[i++];
ans+=a[j].v*(((i-l)*a[j].a-s)+((sl-s)-(mid+1-i)*a[j].a));
t[k++]=a[j];
}
while(i<=mid) t[k++]=a[i++];
for(i=l;i<=r;i++) a[i]=t[i];
return sl+sr;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].v>>a[i].a;
sort(a+1,a+1+n,[](Node a,Node b){return a.v<b.v;});
cdq(1,n);
cout<<ans<<"\n";
return 0;
}

[题解]P5094 [USACO04OPEN] MooFest G 加强版的更多相关文章

  1. P2345 [USACO04OPEN] MooFest G

    简单的一个分块处理:优雅的暴力枚举 #include<bits/stdc++.h>using namespace std; typedef long long ll;const int N ...

  2. ACM ICPC 2018 青岛赛区 部分金牌题题解(K,L,I,G)

     目录: K Airdrop I Soldier Game L Sub-cycle Graph G Repair the Artwork ———————————————————— ps:楼主脑残有点严 ...

  3. luoguP5094 [USACO04OPEN]MooFest 狂欢节

    get 到的 这种需要求 含 max 的式子,枚举最大值的方法非常普遍. 类似的,还有含 min , gcd 的式子,枚举他们也很普遍 主要难点 我们首先想到,先按 v 从小到大排序,因为这样既可以简 ...

  4. 【题解】[USACO07OPEN]Dining G

    \(Link\) \(\text{Solution:}\) 这一题,我们要做到,食物和牛.牛和饮料均为一对一的关系.我们发现这个图不好建立. 经典技巧:将牛拆边,拆成入点和出点,并连容量为\(1\)的 ...

  5. 【题解】[USACO07NOV]Sunscreen G

    \(Link\) \(\text{Solution:}\) 把奶牛的忍耐度转化为线段,则题目转化为选择一些点使得覆盖的线段尽可能多.一个点只能覆盖一条线段. 考虑将点按照位置排序,线段按照右端点排序. ...

  6. [题解] [USACO05JAN]Muddy Fields G

    题目TP门 题目大意 在一个 \(R×C\) 的矩阵中,每个点有两个状态:草地和泥地.你需要在泥地里铺 \(1×k\) 木块, \(k\) 为任意整数,求最少要多少木块. 思路 两个横向木块不会互相干 ...

  7. 【BZOJ】2277: [Poi2011]Strongbox

    题意 有一个密码箱,\(0\)到\(n-1\)中的某些整数是它的密码.如果\(a\)和\(b\)都是它的密码,那么\((a+b)%n\)也是它的密码(\(a,b\)可以相等).某人试了\(k\)次密码 ...

  8. POJ2429 - GCD & LCM Inverse(Miller–Rabin+Pollard's rho)

    题目大意 给定两个数a,b的GCD和LCM,要求你求出a+b最小的a,b 题解 GCD(a,b)=G GCD(a/G,b/G)=1 LCM(a/G,b/G)=a/G*b/G=a*b/G^2=L/G 这 ...

  9. CH Round #54 - Streaming #5 (NOIP模拟赛Day1)

    A.珠 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2354%20-%20Streaming%20%235%20(NOIP模拟赛Day1)/珠 题解:sb题, ...

  10. Largest Submatrix(动态规划)

    Largest Submatrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

随机推荐

  1. CF contest 1935 Round 932 (Div. 2) A-D题解

    Codeforces Round 932 (Div. 2) A-D题解 Codeforces Round 932 (Div. 2) 绪言 很菜,AB速度慢,卡在C,想DP,但是时间优化不下来,说服自己 ...

  2. 洛谷 P6006 [USACO20JAN]Farmer John Solves 3SUM G

    洛谷 P6006 [USACO20JAN]Farmer John Solves 3SUM G Problem 什么是3-SUM? 给你一个序列\(a\),求有多少组\((i,j,k)(1\le i&l ...

  3. C#/.NET/.NET Core优秀项目和框架2025年5月简报

    前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的详细介绍.功能特点.使用方式以及部分功能 ...

  4. python爬虫学习——xlwt库,sqlite库

    xlwt库主要是对excel进行操作,主要流程就是创建对象,创建工作表,写入数据,保存数据表.代码练习如下 ''' import xlwt workbook = xlwt.Workbook(encod ...

  5. Golang操作Kafka

    一.使用库说明 Golang中连接kafka可以使用第三方库:github.com/Shopify/sarama 二.Kafka Producer发送消息 package main import ( ...

  6. 如何在FastAPI中构建一个既安全又灵活的多层级权限系统?

    title: 如何在FastAPI中构建一个既安全又灵活的多层级权限系统? date: 2025/06/14 12:43:05 updated: 2025/06/14 12:43:05 author: ...

  7. 袋鼠云:基于Flink构建实时计算平台的总体架构和关键技术点

    数栈是云原生-站式数据中台PaaS,我们在github和gitee上有一个有趣的开源项目:FlinkX,FlinkX是一个基于Flink的批流统一的数据同步工具,既可以采集静态的数据,也可以采集实时变 ...

  8. CF1923E Count Paths 题解

    CF1923E Count Paths 点分治模板题. 假设当前处理的树根为 \(x\),我们考虑如何统计经过点 \(x\) 的合法路径. \(1\):存在一个与 \(x\) 颜色相同的点,且这个点到 ...

  9. linux 主题

    linux 默认主题见多了之后总会觉得审美疲劳,换一个新鲜的吧 装载自 linux公社 讲的已经比较好了 如果你使用的是图形界面,你会发现Ubuntu默认的界面真是丑的一批,所以下面以Ubuntu 1 ...

  10. 如何打开超过20G的sql文件

    最近在导项目中数据的流程时,对原数据库做了备份,备份好的sql文件有40G左右,通过一番折腾把数据库拿到本地PC,发现PC机直接弄不行: 平时经常使用的NotePad++,提示文本太大无法打开: PC ...