ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【YbtOJ#643】机器决斗

2021-02-14 16:02:04  阅读:196  来源: 互联网

标签:return int YbtOJ sum 决斗 mid update 643 ans


题目

题目链接:https://www.ybtoj.com.cn/contest/113/problem/3

\(n\leq 3\times 10^5,A,D,ATK\leq 10^4\)。

思路

首先直接令 \(b_i=\lceil\frac{d_i}{ATK}\rceil\)。
不难发现如果选择打一个机器人,那么一定会把它打到死。不然先打下一个打死的会更优。
那么问题转化为有一个长度为 \(n\) 的排列 \(p\),我们需要最小化

\[\sum^{n}_{i=1}a_i\times ((\sum_{j=1}^{i}b_i)-1) \]

这个东西跟国王游戏类似,考虑调整法:对于最终序列相邻的两项 \(i,j\),交换他们的代价是 \(a_ib_j-a_jb_i\),也就是说,最终相邻两项必然有 \(a_ib_j>a_jb_i\)。直接排序就可以了。
接下来考虑删除两个机器人后的最小代价。记 \(f_i=a_i(\sum^{i}_{j=1}b_j)-1,g_i=b_i(\sum_{j=i+1}^{n}a_j)\),假设我们删除 \(x,y\) 两个机器人,代价就是

\[(\sum^{n}_{i=1}f_i)-f_x-g_x-f_y-g_y+b_xa_y \]

我们只需要最小化上面这个东西。
考虑枚举 \(x\),那么等价于最大化 \(f_y+g_y-b_xa_y\)。我们可以把这个东西看成一个关于 \(b_x\) 的一次函数,那么其实就是李超树的板子。直接维护区间直线“最大值位置最多”的直线即可。
时间复杂度 \(O(n\log n)\)。
除此之外,还可以用平衡树或者 CDQ 分治维护上凸壳。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=300010;
int rt,n,m;
ll ans,sum,f[N],g[N];

struct node
{
	int a,b;
}a[N];

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

bool check(int x,int i,int j)
{
	return f[j]+g[j]-a[j].a*x<f[i]+g[i]-a[i].a*x;
}

struct SegTree
{
	int tot,lc[N*4],rc[N*4],res[N*4];
	
	int update(int x,int l,int r,int i)
	{
		if (!x) x=++tot;
		int j=res[x];
		if (l==r)
		{
			if (!j || check(l,i,j)) res[x]=i;
			return x;
		}
		if (!j || (check(l,i,j) && check(r,i,j))) return (res[x]=i),x;
		if (!check(l,i,j) && !check(r,i,j)) return x;
		int mid=(l+r)>>1;
		if (f[i]+g[i]>f[j]+g[j])
		{
			if (check(mid,i,j))
				rc[x]=update(rc[x],mid+1,r,j),res[x]=i;
			else
				lc[x]=update(lc[x],l,mid,i);
		}
		else
		{
			if (check(mid,i,j))
				lc[x]=update(lc[x],l,mid,j),res[x]=i;
			else
				rc[x]=update(rc[x],mid+1,r,i);
		}
		return x;
	}
	
	int query(int x,int l,int r,int k)
	{
		if (!x) return 0;
		if (l==r) return res[x];
		int mid=(l+r)>>1,p;
		if (k<=mid) p=query(lc[x],l,mid,k);
			else p=query(rc[x],mid+1,r,k);
		if (!p || check(k,res[x],p)) return res[x];
		return p;
	}
}seg;

int main()
{
	freopen("fittest.in","r",stdin);
	freopen("fittest.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].a,&a[i].b);
		a[i].b=(a[i].b-1)/m+1;
	}
	sort(a+1,a+1+n,cmp);
	for (int i=1;i<=n;i++)
	{
		ans+=a[i].b;
		f[i]=(ans-1)*a[i].a;
		sum+=f[i];
	}
	ans=0;
	for (int i=n;i>=1;i--)
	{
		g[i]=ans*a[i].b;
		ans+=a[i].a;
	}
	ans=sum;
	for (int i=n-1;i>=1;i--)
	{
		rt=seg.update(rt,1,1e4,i+1);
		int j=seg.query(rt,1,1e4,a[i].b);
		ans=min(ans,sum-f[i]-g[i]-f[j]-g[j]+a[i].b*a[j].a);
	}
	printf("%lld",ans);
	return 0;
}

标签:return,int,YbtOJ,sum,决斗,mid,update,643,ans
来源: https://www.cnblogs.com/stoorz/p/14402069.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有