首页 > 其他分享 >【题解】CF1854A2 Dual (Hard Version)

【题解】CF1854A2 Dual (Hard Version)

时间:2023-09-08 15:56:20浏览次数:52  
标签:cnt int 题解 Hard pos Version maxn printf

你考虑我们 A1 只需要通过自加凑一个最大的数,然后将所有的数都变成正数,最后做一次前缀和即可。(不懂可以看看落谷题解)

好,我们现在去看 Hard Version 的 \(31\) 次操作怎么分配:

  • 前缀和(全为正)/ 后缀和 (全为负)—— \(19\) 次

  • 还剩下 \(12\) 次,不知道该怎么做。

我们的目标便变为了:在 \(12\) 次之内让所有数变成全为正/全为负

现在,我们需要整理一下我们手中的方法:

  • 我们 Easy Version 中是怎么做的呢,我们找了一个数,然后让它变成极大/极小,这一步在最劣情况下显然是 \(5\) 次 (\(1\to2\to4\to8\to16\to32\)),然后所有数都要变一遍 —— \(5+n\)
  • 当然,我们也有一种方法就是说找一个绝对值最大的数,然后让它给所有数加一遍,让其他的数和它符号相同 —— \(n\)

当然上面的 \(n\) 其实是上限,准确来说应该将 \(n\) 替换为和选出的数异号的数的个数。

那么,我们就可以将两种方法结合一下。

  • 我们先找到一个绝对值最大的数 \(x\),然后计算和这个数符号相同的数的个数(包括 \(0\))
  • 如果同号的数的个数 \(\geq 7\)(异号的数的个数 \(\leq 12\)),那么就直接让这个这些数都加上 \(x\)(\(\leq 12~times\))
  • 否则,就造一个和 \(x\) 异号的绝对值极大的数,然后将 \(x\) 和与 \(x\) 同号的数都加上这个数。(\(\leq 5 + 6 + 1~times\))

最后将序列变为原序列的前/后缀和序列即可.

code:

#include<bits/stdc++.h>
using namespace std;
const int NN = 40;
int t,n;
int a[NN];
int maxn,pos;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		maxn = 0,pos = 0;
		for(int i = 1; i <= n; ++i){
			scanf("%d",&a[i]);
			if(abs(a[i]) > maxn) maxn = abs(a[i]), pos = i;
		}
		if(maxn == 0){puts("0");continue;}
		int cnt = 0;
		for(int i = 1; i <= n; ++i){
			if(a[i] * a[pos] >= 0 && i != pos) ++cnt;
		}
		if(cnt == n-1){
			printf("%d\n",n-1);
		}
		else if(cnt < 7){
			printf("%d\n",5 + cnt + n);
			for(int i = 1; i <= n; ++i)
				if(a[i] * a[pos] < 0){pos = i;break;}
			for(int i = 1; i <= 5; ++i) printf("%d %d\n",pos,pos);
			for(int i = 1; i <= n; ++i)
				if(a[i] * a[pos] <= 0 && i != pos) printf("%d %d\n",i,pos);
		}
		else{
			printf("%d\n",n - cnt - 1 + n - 1);
			for(int i = 1; i <= n; ++i){
				if(a[i] * a[pos] < 0 && i != pos) printf("%d %d\n",i,pos);
			}
		}
		if(a[pos] > 0) for(int i = 1; i < n; ++i) printf("%d %d\n",i+1,i); 
		else for(int i = n; i > 1; --i) printf("%d %d\n",i-1,i);
	}
} 

标签:cnt,int,题解,Hard,pos,Version,maxn,printf
From: https://www.cnblogs.com/rickylin/p/17687788.html

相关文章

  • 题解 CF1787G【Colorful Tree Again】
    problem贼眉鼠眼有一棵\(N\)个节点的树,这棵树很特殊,每条边都有边权和颜色。果宝特攻会不定时来进攻贼眉鼠眼。具体地,在前\(Q\)个时刻,在每个时刻,会发生以下两个事件之一:果宝特攻摧毁了树上的一个节点\(u\)。贼眉鼠眼修复了树上的一个节点\(u\)。定义一条简单路径......
  • 国标GB28181视频监控EasyGBS接入大量通道时,创建角色接口未响应的问题解决方法
    EasyGBS是一款基于国标GB28181协议的视频云服务平台。它支持多路设备同时接入,并能将视频流以RTSP、RTMP、FLV、HLS、WebRTC等格式分发到多个平台和终端。该平台提供了视频监控直播、云端录像、云存储、检索回放、智能告警、语音对讲、平台级联等功能。在视频能力方面,GB28181视频监......
  • CF868E Policeman and a Tree 题解
    Description.树上警察抓小偷。一名警察速度为\(1\),多名小偷速度为\(+\infty\),问多长时间抓到。树点数\(\le50\)Solution.首先不可能抓不到。其次步数不可能超过\(2500\)(每抓完一个小偷走一遍全图)。这启发我们可以直接暴搜每一步,并记忆化。如果状态设为当前在\(x\),那......
  • 【题解】《PTA-Python程序设计》题目集分享
    第1章-1从键盘输入两个数,求它们的和并输出(30分)本题目要求读入2个整数A和B,然后输出它们的和。输入格式:在一行中给出一个被加数在另一行中给出一个加数输出格式:在一行中输出和值。输入样例:在这里给出一组输入。例如:18-48输出样例:在这里给出相应的输出。例如:......
  • 题解 P8165 [eJOI2021] AddK
    不知道为什么这道题还没有题解。Solution对于操作\(1\),由于\(K\le10\),直接暴力单点修改即可。而操作\(2\)的询问,不难发现,最后结果的呈现形式是\[1\timesA_l+2\timesA_{l+1}+3\timesA_{l+2}+...+3\timesA_{r-2}+2\timesA_{r-1}+1\timesA_r\]其中中间可能有一段系数......
  • SP8177 题解
    2023-09-0111:29:13solution题意:每次询问\([l,r]\)内有多少个数满足可以被所有非\(0\)数位整除。思路看到这个数据范围和题目描述,显然是数位dp。因为\(1\sim9\)的最小公倍数是\(2520\),并且\(2520\)是其他所有\(1\sim9\)子集的最小公倍数的倍数,所以我们只需要......
  • CF402D 题解
    2023-09-0418:42:46solution不难想到我们要先记录一下每一位的前缀\(\gcd\),我们发现我们选择一位的前缀\(\gcd\)除掉以后,前缀\(\gcd\)会变为\(1\)并且会导致这位之后的\(\gcd\)全部为\(1\)。所以每一位只能选择一次,并且我们从后往前扫肯定比从前往后扫要更优。我们......
  • wzOI 2023.8.31 题解
    2023-09-0115:59:41$$前言$$太菜了,第一题都打成那样了没发现是MST,第三题数据范围没有很仔细看,以为是乱搞(组合之类的)题就直接跳了。不得不说这次比赛题目的一些思路还是挺妙的,一些想法确实我这种成分想不太到。$$A$$$$题意$$给出了\(m\)个可以查询的区间\([L_i,R_i]\)......
  • CF1103C 题解
    2023-09-0514:52:07solution找路径很好找,我们随便跑个dfs树找个深度\(\ge\frac{n}{k}\)的路径输出即可。可是怎么找\(k\)个长度不是\(3\)的倍数的环呢?既然我们跑了dfs树,那么就没有横叉边,对于叶子节点非树边只有返祖边,然后一看这个很奇怪的条件——保证每个点度数大......
  • CF1851 部分题解
    2023-07-3019:35:02前言因为我实在是太菜了,没时间也不会做最后两题,所以这里只有前\(5\)道签到题的题解。之后我有时间看了后两题的题解再来更新吧~A先不用看那么多七七八八的,搞清楚下面几点即可:高度不能相同。高度差得被整除。高度差不能太大。好了,然后就可以\(AC\)......