NOIP2023模拟6联测27 点餐

题目大意

有 n n n样菜品,每样菜品都有两个权值 a i a_i ai和 b i b_i bi,如果你选择了 k k k个菜品,分别为 p 1 , ... , p k p_1,\dots,p_k p1,...,pk,则你的花费为

∑ i = 1 k a p i + max ⁡ i = 1 k b p i \sum\limits_{i=1}^ka_{p_i}+\max\limits_{i=1}^kb_{p_i} i=1∑kapi+i=1maxkbpi

对于每个 1 ≤ k ≤ n 1\leq k\leq n 1≤k≤n,求如何选 k k k个菜品才能使花费最小,并输出最小花费。

1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ a i , b i ≤ 1 0 9 1\leq n\leq 2\times 10^5,1\leq a_i,b_i\leq 10^9 1≤n≤2×105,1≤ai,bi≤109

时间限制 2000 m s 2000ms 2000ms,空间限制 512 M B 512MB 512MB。

题解

前置知识:可持久化线段树(主席树)

首先,我们考虑如何求 k k k固定时的答案。将所有菜品按 b b b值从小到大排序,如果 b b b值相同则按 a a a值从小到大排序。枚举第 x x x个菜品作为选中的 b b b最大的菜品,那么剩下的 k − 1 k-1 k−1个菜品肯定是选择前 x − 1 x-1 x−1个菜品中 a a a最小的 k − 1 k-1 k−1个盘子。对于给定的 k k k和 x x x,用可持久化线段树可以用 O ( n log ⁡ n ) O(n\log n) O(nlogn)的时间复杂度来求出对应方案的值,我们将其记为 w ( k , x ) w(k,x) w(k,x)。

令 f ( k ) f(k) f(k)表示在取 k k k个菜品时能得到最优解的 x x x,对于两个不同的决策 x , y x,y x,y( x < y x<y x<y),若 w ( k , x ) ≥ w ( k , y ) w(k,x)\geq w(k,y) w(k,x)≥w(k,y),那么增大 k k k之后因为 y y y的可选择范围包含了 x x x的可选择范围,所以 y y y新选的 a a a值一定不大于 x x x新选的 a a a值,即 w ( k ′ , x ) ≥ w ( k ′ , y ) w(k',x)\geq w(k',y) w(k′,x)≥w(k′,y)对 k ≤ k ′ ≤ n k\leq k'\leq n k≤k′≤n恒成立。由此可得 f ( 1 ) ≤ f ( 2 ) ≤ ⋯ ≤ f ( n ) f(1)\leq f(2)\leq\cdots\leq f(n) f(1)≤f(2)≤⋯≤f(n),即最优决策具有单调性,可以用分治求解。

在分治的时候,用 s o l v e ( s l , s r , l , r ) solve(sl,sr,l,r) solve(sl,sr,l,r)表示用 x ∈ [ l , r ] x\in [l,r] x∈[l,r]来给 k ∈ [ s l , s r ] k\in [sl,sr] k∈[sl,sr]计算答案。一开始是 s o l v e ( 1 , n , 1 , n ) solve(1,n,1,n) solve(1,n,1,n),将其分成若干个子问题分别来解决。对于每个子问题,令 m i d = ( s l + s r ) / 2 mid=(sl+sr)/2 mid=(sl+sr)/2,则我们先在 [ l , r ] [l,r] [l,r]中找到 f ( m i d ) f(mid) f(mid),设 f ( m i d ) = p o s f(mid)=pos f(mid)=pos,则 [ s l , m i d − 1 ] [sl,mid-1] [sl,mid−1]的 f f f值在 [ l , p o s ] [l,pos] [l,pos]上, [ m i d + 1 , s r ] [mid+1,sr] [mid+1,sr]的 f f f值在 [ p o s , r ] [pos,r] [pos,r]上,那我们就可以将原问题分为两个子问题 s o l v e ( s l , m i d − 1 , l , p o s ) solve(sl,mid-1,l,pos) solve(sl,mid−1,l,pos)和 s o l v e ( m i d + 1 , s r , p o s , r ) solve(mid+1,sr,pos,r) solve(mid+1,sr,pos,r)。

在分治的时候,最多只会往下推 O ( log ⁡ n ) O(\log n) O(logn)层,每层需要求 O ( n ) O(n) O(n)个 w ( k , x ) w(k,x) w(k,x)的值,总共需要求 O ( n log ⁡ n ) O(n\log n) O(nlogn)个 w ( k , x ) w(k,x) w(k,x)的值,所以时间复杂度为 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)。

code

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=200000;
int n,tot=0,rt[N+5],re[N+5];
long long ans[N+5];
struct node{
	int a,b;
}w[N+5];
struct tree{
	int lc,rc,hv;
	long long s;
}tr[N*20+5];
bool cmp1(node ax,node bx){return ax.a<bx.a;}
bool cmp2(node ax,node bx){return ax.b<bx.b;}
void ch(int &r1,int r2,int l,int r,int v){
	r1=++tot;
	tr[r1]=tr[r2];
	if(l==r){
		++tr[r1].hv;
		tr[r1].s+=re[l];
		return;
	}
	int mid=l+r>>1;
	if(v<=mid) ch(tr[r1].lc,tr[r2].lc,l,mid,v);
	else ch(tr[r1].rc,tr[r2].rc,mid+1,r,v);
	tr[r1].hv=tr[tr[r1].lc].hv+tr[tr[r1].rc].hv;
	tr[r1].s=tr[tr[r1].lc].s+tr[tr[r1].rc].s;
}
long long find(int k,int l,int r,int v){
	if(l==r) return tr[k].s;
	int mid=l+r>>1;
	if(tr[tr[k].lc].hv>=v) return find(tr[k].lc,l,mid,v);
	else return find(tr[k].rc,mid+1,r,v-tr[tr[k].lc].hv)+tr[tr[k].lc].s;
}
void solve(int sl,int sr,int l,int r){
	if(sl>sr) return;
	int mid=sl+sr>>1,pos=0;
	for(int i=max(mid,l);i<=r;i++){
		long long now=w[i].b+find(rt[i],1,n,mid);
		if(ans[mid]>=now){
			ans[mid]=now;pos=i;
		}
	}
	solve(sl,mid-1,l,pos);
	solve(mid+1,sr,pos,r);
}
int main()
{
//	freopen("order.in","r",stdin);
//	freopen("order.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&w[i].a,&w[i].b);
		ans[i]=1e18;
	}
	sort(w+1,w+n+1,cmp1);
	for(int i=1;i<=n;i++){
		re[i]=w[i].a;w[i].a=i;
	}
	sort(w+1,w+n+1,cmp2);
	for(int i=1;i<=n;i++) ch(rt[i],rt[i-1],1,n,w[i].a);
	solve(1,n,1,n);
	for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
	return 0;
}
相关推荐
YRr YRr24 分钟前
在Windows上安装WSL2和Ubuntu 20.04以搭建C++开发环境的详细指南
c++·windows·ubuntu·wsl2
Farewell_me39 分钟前
C++模拟实现list:list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍
c++·list
hong1616881 小时前
VSCode中配置C/C++环境
c语言·c++·vscode
小羊在奋斗1 小时前
【C++】探秘二叉搜索树
c++·人工智能·神经网络·机器学习
白葵新2 小时前
PCL addLine可视化K近邻
c++·人工智能·算法·计算机视觉·3d
MustardJim2 小时前
Visual Studio 引入外部静态库与动态库
c++·visual studio
挽月0012 小时前
C++单例模式
开发语言·c++·单例模式
机器视觉知识推荐、就业指导2 小时前
Qt/C++ TCP调试助手V1.1 新增图像传输与接收功能(附发布版下载链接)
c++·qt·tcp/ip
wx200411023 小时前
Codeforces Round 973 (Div. 2) - D题
数据结构·c++·算法
DieSnowK3 小时前
[项目][WebServer][CGI机制 && 设计]详细讲解
linux·开发语言·c++·http·项目·webserver·cgi机制