首页 > 其他分享 >CF1834 题解

CF1834 题解

时间:2023-06-27 22:36:54浏览次数:38  
标签:int 题解 复杂度 cin st 端点 CF1834 lcm

CF1834 题解

A

考虑答案与元素位置无关,只与\(1\)和\(-1\)的个数有关。要求\(1\)必须多于或等于\(-1\),并且\(-1\)个数为偶数。分讨:

序列中\(num(1) \geq num(-1)\),只需要看\(num(-1)\)正负性,奇数1步,偶数0步

序列中\(num(1) < num(-1)\),先通过\(-1\)变\(1\)将数目补到第一种情况,再做第一种情况即可。

时间复杂度\(O(n)\)。

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
int a[N],n,s[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;
		memset(a,0,sizeof(a));
		memset(s,0,sizeof(s));
		for(int i = 1;i <= n;i++) cin>>a[i],s[i] = s[i - 1] + a[i];
		if(s[n] >= 0) cout<<((n - s[n]) % 4 == 0 ? 0 : 1)<<endl;
		else cout<<((n / 2) % 2 == 0 ? (-s[n] + 1) / 2 : (-s[n] + 1) / 2 + 1)<<endl;
	}
	return 0;
}

B

考虑\(9\)和\(0\)对应一定是最大的,我们尽量凑成\(9\)和\(0\)配对的情况。将\(L\)和\(R\)用前导0补齐,我们不难发现在前面若干个相同的数位是无法产生贡献的,直到第一个不同的数位时,将\(L\)往上取,这一位后面全部赋为9,\(R\)往下取,这一位后面全部赋为0,这样就保证这一位的贡献没有下降,后面的贡献都取到了最大值,从而是最优解。

时间复杂度\(O(n)\)。

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
int n,m;
char a[N],b[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		scanf("%s",a + 1);
		scanf("%s",b + 1);
		n = strlen(a + 1);
		m = strlen(b + 1);
		if(n < m) 
		{
			for(int i = n;i >= 1;i--) a[i + m - n] = a[i];	
			for(int i = 1;i <= m - n;i++) a[i] = '0';
		}
		int ans = 0;
		for(int i = 1;i <= m;i++)
			if(a[i] != b[i])
			{
				ans += (m - i) * 9 + abs(b[i] - a[i]);
				break;
			}
		cout<<ans<<endl;
	}
	return 0;
}

C

既然Alice想要将步数最小化,那么她就要尽量将两个字符串之间的差异消掉。我们发现\(S,T\)的对应方式只有两种\((s_1 \to t_1,s_n\to t_n \ 和\ s_1\to t_n,s_n\to t_1)\)。所以Bob翻转哪个串都只是改变了一次对应方式,如果Alice一开始就按照一种对应方式消除差异的话,Bob完全干扰不了Alice,所以得出结论:Bob是小丑,最多只能将步数拖1步,选择权在于Alice。

宁愿当小丑也在所不惜,全力以赴地进行着必输的游戏......仅仅是他深爱着她。

上文说了,只有两种对应方式,所以Alice自然选的就是步数小的那个。我们发现由于Alice改变一次,Bob就要翻转一次,所以步数等于对应方式的差异数乘2,根据差异数的奇偶性和对应顺序决定是否需要-1(Bob最后一次翻之前就对应上了)

时间复杂度\(O(n)\)。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
char s[N],t[N];
int n;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;
		scanf("%s",s + 1);
		scanf("%s",t + 1);
		int dif = 0,rdif = 0,step = 0,rstep = 0;
		for(int i = 1;i <= n;i++) if(s[i] != t[i]) ++dif;
		for(int i = 1;i <= n;i++) if(s[i] != t[n + 1 - i]) ++rdif;
		step = dif << 1;
		if(dif & 1) step--;
		if(dif == 0) step = 0;
		rstep = rdif << 1;
		if(!(rdif & 1)) rstep--;
		if(rdif == 0) rstep = 2;
		cout<<min(step,rstep)<<endl;
	}
	return 0;
}

D

考虑到对于一个人,如果他是极差中的最大值,那么所选的点就是他学过的所有点(对于学过的,多选一个他的高度就+1,最小值的高度可能+1,一定不劣;对于他没学过的,选了以后他的高度不变,最小值的高度可能+1,一定不优)。

所以我们可以枚举这个最大值是谁,可能的最小值与这个人可能有3种关系:不交,相交,最小值包含于这个人。先不考虑包含,这一部分很简单,我们尽量选一个人让他们不交,所以记录全场最大右端点和最小左端点即可,因为取这两个端点对应的线段一定是与中间的最大值交集最小的,与两边的交集大小取\(min\)就是交集大小了。

对于包含关系,我们发现与最大值交集最小的,一定是包含于他的人中学的最少的人,考虑二维关系不好维护,就将人按照右端点排序,从小到大遍历右端点,在以左端点为下标的树状数组中找比当前左端点大的当中学的最少的人,就是这个最大值对应的答案。

时间复杂度\(O(n\log n)\)。

解释:代码中对于“比当前左端点大的”这个后缀操作,在离散化左端点时将其反序存储,转化为树状数组的前缀问题。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5,inf = 0x3f3f3f3f;
struct Seg{
	int l,r;
}x[N];
int n,maxl,minr,m,xl[N],cnt = 0,inc[N];
map<int,int> rev;
struct BIT{
	int a[N];
	inline void init()
	{
		for(int i = 1;i <= n;i++) a[i] = inf;
	}
	inline int lowbit(int x)
	{
		return x & (-x);
	}
	inline int query(int x)
	{
		if(!x) return inf;
		return min(query(x - lowbit(x)),a[x]);
	}
	inline void modify(int x,Seg k)
	{
		if(x > cnt) return;
		a[x] = min(a[x],k.r - k.l + 1);
		modify(x + lowbit(x),k);
	}
}p;
inline bool cmp(Seg a,Seg b)
{
	if(a.r ^ b.r) return a.r < b.r;
	else return a.l > b.l;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		maxl = 0,minr = 2e9;cnt = 0;
		rev.clear();
		p.init();
		for(int i = 1;i <= n;i++)
		{
			cin>>x[i].l>>x[i].r;
			xl[i] = x[i].l;
			maxl = max(maxl,x[i].l);
			minr = min(minr,x[i].r);
		}
		sort(xl + 1,xl + n + 1);
		cnt = unique(xl + 1,xl + n + 1) - (xl + 1);
		for(int i = 1;i <= cnt;i++) rev[xl[i]] = cnt + 1 - i;
		sort(x + 1,x + n + 1,cmp);
		for(int i = 1;i <= n;i++)
		{
			inc[i] = p.query(rev[x[i].l]);
			p.modify(rev[x[i].l],x[i]);
		}
		int ans = 0;
		for(int i = 1;i <= n;i++)
		{
			int inter = min(min(max(x[i].r - maxl + 1,0),max(minr - x[i].l + 1,0)),inc[i]);
			ans = max(ans,(x[i].r - x[i].l + 1 - inter) << 1);
		}
		cout<<ans<<endl;
	}
	return 0;
}

E

我们发现如果一个素数是一些数的\(lcm\),当且仅当这个素数单独作为一个元素出现了,所以答案一定不超过第\(n + 1\)个素数的大小,我们发现第\(3e5\)个素数大致在\(6e6\)左右。

考虑到一个暴力,对于每个点\(i\)开始,暴力向右扫描\(j\),求出\([i,j]\)中元素的\(lcm\)并加进桶里,如果\(lcm\)大于了第\(n + 1\)个素数的大小,就停止对\(j\)的扫描(因为数更多\(lcm\)一定不减)。

这样暴力复杂度是\(O(n^2\log n)\)的,无法通过,我们发现我们只需要检查一个\(lcm\)是否出现过,想办法在向右扫的时候跳过\(lcm\)相同的一段,这个可以预处理一个\(lcm\)的\(st\)表,然后每次倍增来跳过,理论上比原来还多一个\(\log\)。

按这个写一发,你就会发现你AC了。

因为这样优化后,时间复杂度就有了保证,考虑向右扫时每次\(lcm\)的变化都会让\(lcm\)的值起码乘上2,所以最多只会变化\(O(\logV)\)次(\(V\)是值域)。单次扫描复杂度就降为了\(O(\log n \log V)\),总复杂度\(O(n\log n\log V)\)

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5,M = 6e6 + 5;
typedef long long ll;
ll a[N],st[20][N],n;
int prime[N * 5],tot = 0,lim;
bool vis[M];
inline void init()
{
	for(int i = 2;i <= M - 1;i++)
	{
		if(!vis[i])
			prime[++tot] = i;
		for(int j = 1;j <= tot && 1ll * i * prime[j] <= M - 1;j++)
		{
			vis[i * prime[j]] = 1;
			if(!(i % prime[j])) break;
		}
	}
	memset(vis,0,sizeof(vis));
}
inline int lcm(int x,int y)
{
	if(x == -1 || y == -1) return -1;
	ll p = 1ll * x / __gcd(x,y) * y;
	if(p > lim) return -1;
	return p;
}
inline int fd(int x,int &val)
{
	for(int i = 19;i >= 1;i--)
		if(lcm(val,st[i][x]) == val) x += (1 << i) - 1;
	val = lcm(val,st[0][x + 1]);
	return x + 1;
}
int main()
{
	int T;
	init();
	cin>>T;
	while(T--)
	{
		cin>>n;lim = prime[n + 1];
		for(int i = 1;i <= lim;i++) vis[i] = 0;
		for(int i = 1;i <= n;i++) 
		{
			cin>>a[i];st[0][i] = a[i];
			if(st[0][i] > lim) st[0][i] = -1;
		}
		for(int i = 1;i <= 19;i++)
			for(int j = 1;j <= n;j++)
			{
				if((1 << i) + j - 1 > n) st[i][j] = -1;
				else st[i][j] = lcm(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
			}
		for(int i = 1;i <= n;i++)
		{
			int tp = i,now = st[0][i];
			while(tp <= n && now != -1)
			{
				vis[now] = 1;
				tp = fd(tp,now);
			}
		}
		for(int i = 1;i <= lim;i++)
			if(!vis[i]) 
			{
				cout<<i<<endl;
				break;
			}
	}
	return 0;
}

F

咕。

标签:int,题解,复杂度,cin,st,端点,CF1834,lcm
From: https://www.cnblogs.com/TheLastCandy/p/17510063.html

相关文章

  • CF1834
    CF1834VirtualContest做了5道题,非常不错。A.UnitArray秒切题,判断个数,然后判断一下奇偶即可。提交:https://codeforces.com/contest/1834/submission/211190220B.MaximumStrength题目描述每一种材料的力量由一个十进制整数表示。对于一个武器,由两种材料构成。假如第......
  • mac打开ddms卡住的问题解决
    https://blog.csdn.net/qq_35244415/article/details/110656444?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-110656444-blog-88994745.235^v38^pc_relevant_default_base&depth_1-utm_source=distribute.......
  • P4630 [APIO2018] 铁人两项 题解
    一、题目描述:给你一个$n$个点,$m$条边的无向图。图不一定联通求出点对$(u,c,v)$的数量,使得点$u$存在一条经过点$c$到达点$v$的无向图。数据范围:$1\len\le1\times10^5,1\lem\le2\times10^5$ 二、解题思路:算是圆方树比较模板的题了......
  • CF1834 Div.2 做题记录
    A题面分类讨论即可点击查看代码#include<bits/stdc++.h>#defineullunsignedlonglong#definelllonglong#definepiipair<int,int>#definepdipair<double,int>#definepbpush_back#defineeps1e-9#definempmake_pairusingnamespacestd;namesp......
  • B0626 模拟赛题解
    原题链接前言重庆一位金牌大佬出的。感受:除了最后一题,感觉难度不如C组,甚至没之前D组题难?T1浪费2.5h,最后还是打表秒了。T2想出正解,但发现是数据结构题,最后40min怒打100行,差点打出正解。T3花20min打出20分部分分,赛后发现XD秒了(tql)。T4看题浪费5min......
  • vue3引入bootstrap5的折叠菜单无效问题解决
    问题:通过npm后者yarn安装bootstrap5后,在入口文件全局引入bootstrap5的js、scc,在vue组件引入折叠功能,点击可以正常展开,在点击无法收回解决办法:可参考网上博主的建议,大概意思就是之前引入的js文件不对,导致收回方法没有执行import'bootstrap/dist/js/bootstrap.bundle'main入口......
  • CodeForces 605E Intergalaxy Trips 题解
    题意有一张\(n\)个点的有向完全图,边\(i\toj\)有\(p_{i,j}\)的概率出现(\(p_{i,i}=1\))。你要从\(1\)开始,每天可以走一条出边或留在原地,求最优策略下走到\(n\)的期望天数。输出小数(不取模)。\(n\le10^3\)思路设\(f(i)\)表示从\(i\)走到\(n\)的期望天数,那么......
  • P3387 【模板】缩点 题解
    一、题目描述:给你一个$n$个点,$m$条边的有向图。点带权。求一条路径经过的所有点的权值和最大是多少。点可以重复经过。数据范围:$1\len\le1\times10^4,1\lem\le1\times10^5$。 二、解题思路:缩点板子题,不需要思路。时间复杂度$O(n+m)$。......
  • 复旦大学2022--2023学年第二学期(22级)高等代数II期末考试第八大题解答
    八、(10分) 设$n$阶实方阵$A$满足$A^3=A$,证明: 若对任意的实列向量$x$,均有$x'A'Ax\leqx'x$,则$A$是实对称阵.证法一(几何证法) 将题目转换成几何语言:设$\varphi$是$n$维欧氏空间$V$上的线性算子,满足$\varphi^3=\varphi$,若对$V$中任一向量$v......
  • P3388 【模板】割点(割顶) 题解
    一、题目描述:给你一个$n$个点,$m$条边的无向图。求出所有割点,按节点编号升序排序。数据范围:$1\len\le2\times10^4,1\lem\le1\times10^5$。 二、解题思路:板子题,不需要思路。时间复杂度$O(n+m)$。 三、完整代码:1#include<iostream>......