首页 > 其他分享 >AT_abc373_e 的题解

AT_abc373_e 的题解

时间:2024-10-01 22:45:10浏览次数:7  
标签:二分 val int 题解 mid pos abc373 define

(一)

二分套二分。(感觉是一个很麻烦的做法。)

题目问的是让额外给的票最少,考虑二分答案。

设二分的答案为 \(x\),该候选人原来的得票为 \(v\),想要超过他至少要 \(x+v+1\)。

同时用前缀和维护区间和。

第一种情况为该候选人在前 \(m\) 个人中,如下图所示。

logo

绿色箭头为被讨论的人,蓝色箭头表示 \(x+v+1\) 在原数组中的位置,蓝勾的则是最劣情况下超过当前候选人的人。

可以计算出蓝勾位置原来的和与最劣下和的差,是否够分配。

蓝色箭头指向位置可以二分。(其实是我不会 lower_bound。)

第二种情况是当前候选人不在前 \(m\) 位,那么无脑选前 \(m\) 中小于 \(x+v+1\) 的即可。

其实两种情况相差不大,但赛时代码又臭又长。

特别鸣谢:Daniel234 在赛时的口头鼓励,虽然毫无用处,但他与 *1300 斗智斗勇始终印象深刻。

(二)

AC 代码。

// LUOGU_RID: 179341441
//2024-09-28 20:13:53
#include<bits/stdc++.h>
#define db double
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define mkp make_pair
#define pii pair<int,int>
#define int long long
using namespace std;
bool MBE;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f; 
}
const int mxn=2e5+10;
int ans[mxn],s,n,m,k,sum[mxn];
struct node{
	int val,pos;
}a[mxn];
bool cmp(node x,node y){
	return x.val>y.val;
}
int query1(int pos,int x){
	int t=a[pos].val+x+1,p=k-x,ss;
	int l=1,r=m+1,ans=1;
	while(l<=r){
		int mid=(l+r)>>1;
		if(a[mid].val<=t)ans=mid,r=mid-1;
		else l=mid+1;
	}
	if(ans==pos){
		ans++;
		ss=sum[m+1]-sum[ans-1];
		return (k-x)<t*(m-ans+2)-ss;
	}
	ss=sum[m+1]-sum[ans-1]-a[pos].val;
	return (k-x)<t*(m-ans+1)-ss;
}
int query2(int pos,int x){
	if(a[pos].val+x<a[m].val)return 0;
	int l=1,r=m,ans=1,p=a[pos].val+x+1;
	while(l<=r){
		int mid=(l+r)>>1;
		if(a[mid].val<=p)ans=mid,r=mid-1;
		else l=mid+1;
	}
	int ss=sum[m]-sum[ans-1];
	return (k-x)<p*(m-ans+1)-ss;
}
signed main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    n=read(),m=read(),k=read();
    if(n==1){
    	puts("0");
    	return 0;
    }
    if(m==n){
    	for(int i=1;i<=n;i++)
    		printf("0 ");
    	return 0;
    }
    for(int i=1;i<=n;i++){
    	a[i]=(node){read(),i};
    	s+=a[i].val;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)
    	sum[i]=sum[i-1]+a[i].val;
    k-=s;
    for(int i=1;i<=m;i++){
    	int l=0,r=k,res=-1;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(query1(i,mid))r=mid-1,res=mid;
    		else l=mid+1;
    	}
    	ans[a[i].pos]=res;
	}
	for(int i=m+1;i<=n;i++){
    	int l=0,r=k,res=-1;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(query2(i,mid))r=mid-1,res=mid;
    		else l=mid+1;
    	}
    	ans[a[i].pos]=res;
	}
	for(int i=1;i<=n;i++)
		printf("%lld ",ans[i]);    
	bool MED;
    cerr<<(&MED-&MBE)/1048576.0<<" MB, "<<1000*clock()/CLOCKS_PER_SEC<<" ms\n";
    return 0;
}

标签:二分,val,int,题解,mid,pos,abc373,define
From: https://www.cnblogs.com/Jh763878/p/18444228

相关文章

  • 优美函数 题解
    题意简述给你函数\(f\):\[f(x,y,u)=\left\{\begin{array}{rcl}u-y,&x=1\\u,&1<x\ley,\\gcd(x,y)=1\\-x\cdoty,&x\neq1,\\gcd(x,y)=x\\0,&\text{otherwise}.\end{array}\right.\]对于一个长度为\(n\)的序列......
  • ABC 模拟赛 | A Passing Contest 001题解记录(A,B,C,D)
    比赛链接https://www.luogu.com.cn/contest/126344[APC001]A-CT不必多说,多次取模#include<iostream>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<deque>#include<math.h>#include<map>......
  • CF1214G Feeling Good 题解
    题目链接点击打开链接题目解法我真菜啊,感觉每一步都不难,但一步都没想到/yun考虑两行\(x,y\)什么时候可以构造出合法的矩形?即\(x\)中需要有\(y\)对应位置为\(0\)的\(1\),\(y\)中需要有\(x\)对应位置为\(0\)的\(1\)归纳一下,\(x\)不是\(y\)的子集且\(y\)不......
  • ABC373 D-F 详解
    D思路说是有向图,实际上可以看作是无向图。因为如果有\(x_{v_j}-x_{u_j}=w_j\),那么就一定有\(x_{u_j}-x_{v_j}=-w_j\)。因为题目保证给出的数量关系没有冲突,所以如果我们知道了一个结点\(a\)的值,那么所有与它有数量关系的结点\(b\)的值都能被推出。从而如果一个连......
  • CF2018E2 Complex Segments (Hard Version) 题解
    题目描述\(T\)组数据,给定\(n\)条线段\([l_i,r_i]\),称一个线段集合是复杂的,当且仅当:它可以被划分成若干个大小相等的线段组。两条线段相交当且仅当它们在同一组。求用这\(n\)条线段构成的复杂线段集合的最大值。数据范围\(1\len,\sumn\le3\cdot10^5\)。\(1\l......
  • CF280C Game on Tree题解
    题目描述给定一棵有根树,结点编号从1到n。根结点为1号结点。对于每一次操作,等概率的选择一个尚未被删去的结点并将它及其子树全部删去。当所有结点被删除之后游戏结束。也就是说,删除1号结点后游戏即结束。要求求出删除所有结点的期望操作次数。不是哥们,我好不容易国庆......
  • 题解:AtCoder Beginner Contest AT_abc373_d ABC373D Hidden Weights(格式美化版)
    题目传送门题目翻译给你一个NNN个点,MMM条边的有向图,其中边有边......
  • CF429E Points and Segments 题解
    题目链接点击打开链接题目解法真难啊/yun把区间染成红色看作区间\(+1\),染成蓝色看作区间\(-1\),要求是每个点上的数\(\in\{-1,0,1\}\)可以选择的数有\(-1,1\)不太好做,我们考虑将限制变成每个点上的数只能为\(0\)我们记经过点\(x\)的线段数量为\(cnt_x\)如果\(cnt......
  • 题解:P11075 不等关系 加强版
    这是洛谷转移过来的题解,作者是4041nofoundGeoge(我自己,记得关注呀)题目大意对于一个字符串s1,s......
  • [HNOI2010] 城市建设 题解
    题意给定一个图,每次修改一条边的边权,每次修改后输出该图的最小生成树边权和,询问间不独立。思路在线不好做,考虑离线下来,可以使用线段树分治。我们称在当前区间\(\left[l,r\right]\)的边为动态边,不在的边为静态边。但这样每次遍历到叶子节点的时候静态边的数量都是\(m\)的......