首页 > 其他分享 >CF1920D题解

CF1920D题解

时间:2024-08-06 21:26:30浏览次数:15  
标签:abcd cnt 题解 sum CF1920D 18 序列 ll

题面

这里不再赘述了,直接搬个链接。
In Luogu
In Codeforces

思路

存储

一共两种操作:要么在末尾加一个数 x x x,要么把整一段复制 x x x 次。前一个简单,直接加上去就行了,但第二个……它复制上那么一顿,如果直接记录的话,第一爆空间,第二,查找的时候找都没法找(毕竟谁会一个个枚举呢)!

那么我们考虑第二种操作。

设原序列为 abcd \texttt {abcd} abcd,多复制 5 5 5 份,那么序列变成:

abcd   abcd   abcd   abcd   abcd   abcd \texttt {abcd abcd abcd abcd abcd abcd} abcd abcd abcd abcd abcd abcd

注意:多复制 x x x 份指在原序列末尾增加 x x x 份,即序列长度变为原序列的 x + 1 x + 1 x+1 倍!

现在,我们取第 18 18 18 个数。第 18 18 18 个数是第 5 5 5 个区间的第 2 2 2 个数。但整个数列是被 copy 过的,所以……发现什么了?

第 18 18 18 个数和第 2 2 2 个数不是一个数吗!第 k k k 个区间的第 x x x 个数,跟第一个区间的第 x x x 个数,不是一样吗!

问题变简单了,序列长度大幅缩水。

但我们总要记录区间长度吧,总之你得找着这个数是谁,在哪。

所以,在每次操作的后面,我们都记录一下操作结束后序列长度,这样那么老长的序列就变为一个数字了。另外,为了优惠第一个操作,我们还要记录下每次操作完后序列的最后一个数是谁。

但是还有个问题。如果第二个操作做多了,序列长度还是会爆表,直接炸了 longlong。但好在题目的询问中只询问到 1 0 18 10^{18} 1018,所以……后面的各种内容,我们……直接扔了不要了!(好粗暴哈哈哈)


查询

存是存完了,找呢?

嘿嘿,用二分,而且是直接二分。

如果我们要查的这个数在这个区间的范围内——换句话说,就是第 k k k 次操作范围包含了第 x x x 个数,我们就返回区间数。如果不符合范围,就朝两边查找。这是一个非常基本的二分查找。

当然了,要避坑。如果查的数是第 k − 1 k - 1 k−1 个区间的末尾,就会发生奇奇怪怪的死循环。另外,在存储的时候,如果复制操作后的区间有一半超过 1 0 18 10^{18} 1018 的线了,如果整个区间全部切掉,也会导致查找区间不在存储范围内而死循环。

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 5;
const ll N = 1e18;
int t , n , q;
int lst[maxn] , b;
ll sum[maxn]; 
//sum[i]:第i次操作结束后,序列长度 
//lst[i]:第i次操作结束后,序列的最后一个数
//那么如果sum[i]>1e18,不再记录任何值(你查询区间都不到那你记它干嘛) 
int cnt; //记录2操作的数量 
ll ffind(ll pos , ll l , ll r) {
	ll mid = (l + r) >> 1;
	if(pos > sum[mid - 1] && pos <= sum[mid]) return mid;
	else if(pos == sum[mid - 1]) return mid - 1;
	else if(pos > sum[mid]) ffind(pos , mid + 1 , r);
	else ffind(pos , l , mid);
}
int main() {
//	freopen("CF1920D.in" , "r" , stdin);
//	freopen("CF1920D.out" , "w" , stdout);
	ios :: sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t --) {
		b = 0;
		cin >> n >> q;
		int flag = 1;
		//cout << "I'm alive!" << endl;
		for(int i = 1 ; i <= n ; ++ i) {
			int opt , x;
			cin >> opt >> x;
			if(flag && opt == 1 && sum[i - 1] + 1 <= N) {
				++ b;
				sum[i] = sum[i - 1] + 1;
				lst[i] = x;
			}
			else if(flag && sum[i - 1] <= N / (x + 1)) {
				++ b;
				sum[i] = sum[i - 1] * (x + 1);
				lst[i] = lst[i - 1];
			}
			else if(flag && sum[i - 1] < N) {
				++ b;
				sum[i] = N;
				lst[i] = -1;
			}
			else flag = 0;
		}
//		cout << "!" << b << endl;
//		cout << endl << endl << endl;
//		for(int i = 1 ; i <= b ; ++ i) {
//			cout << sum[i] << " " << lst[i] << endl;
//		}
//		cout << endl << endl << endl;
		for(int i = 1 ; i <= q ; ++ i) {
			ll k;
			cin >> k;
			ll cnt = ffind(k , 1 , b);
			while(k != sum[cnt] || lst[cnt] == -1) {
				k %= sum[cnt - 1];
				if(k == 0) k = sum[cnt - 1];
				cnt = ffind(k , 1 , cnt - 1);
			}
			cout << lst[cnt] << " ";
			
		}
		cout << endl;
	}
	return 0;
}

标签:abcd,cnt,题解,sum,CF1920D,18,序列,ll
From: https://blog.csdn.net/Tamera_Clinton/article/details/140834658

相关文章

  • NSSCTF靶场题解(6)
    站在小白的视角上,写了在写题目的wp方面更多是想体现题目思考的逻辑和细节,更多是写给同样新手小白的内容,解题方面为什么从这一步到下一步的,很助于培养思考题目的逻辑思维,尽我所能把细节阐释到位,有些地方可能理解说辞不是特别到位,如果有问题就麻烦各位大佬师傅指点~这次题解库收......
  • 题解:CF257C View Angle
    题目传送门题意平面上有\(n\)个点。从原点引出两条射线,将平面分成两个部分,使其中一个部分覆盖所有的点。求这个部分与原点所夹的角的最小度数。思路既然一个部分覆盖了所有的点,那么另一个部分就一个点都没覆盖,那么要让这个部分最优,这两条射线一定经过两个中间没有任何点的点......
  • 【题解】暑假集训CSP提高模拟14
    目录Rank&挂分A.BA题目内容部分分10pts10+20pts正解思路代码B.BB题目内容部分分5pts正解思路代码C.BCD.BDRank&挂分T4暴搜后来改了记搜,不知道哪里锅了,挂5pts。A.BA题目内容现在有\(m\)块烙板,\(n\)张饼,第\(i\)张饼需要烙\(a_i\)个单位时间,一张饼一个单位时刻只能......
  • 2024MX-MF-DAY1-text题解
    T1【题目描述】有\(n\)个人按编号从\(1\)到\(n\)坐成一圈,即第\(i\in[1,n]\)个人右边是\(i+1\),第\(n\)个人右边的人是\(1\)。初始,每个人手上有\(m\)个球。随后,\(n\)个人按编号从小到大的顺序依次执行如下操作:把自己手中的球分成数量相同且尽可能多的三份,......
  • AkSoundSeedAir.dll修复指南:游戏音频问题解决与预防技巧
    AkSoundSeedAir.dll是一个与声音引擎相关的动态链接库(DynamicLinkLibrary,简称DLL)文件,尤其与Wwise(AudiokineticWwise)声音设计和游戏音效中间件有关。Wwise是一个广泛应用于游戏开发的声音引擎,用于处理游戏中的音频和音效,AkSoundSeedAir.dll就是Wwise的一部分,用于实现声音处理......
  • 花园改造 题解
    题目id:9989题目描述小\(X\)开始改造她的环形的花园了,具体来说她要在花园的环上种满\(n\)棵树。她现在有\(3\)种树:种子、小树苗和大树。每个位置上种不同的树会产生不同的满意度,具体来说在第\(i\)个位置,种种子会产生\(a_i\)的满意度,种小树苗会产生\(b_i\)的满意度,种大树会产生\(c......
  • [AGC005B] Minimum Sum 题解
    题目传送门看到这道题很多人用单调栈,其实用笛卡尔树本质差不多,但是思维难度更小。不知道笛卡尔树的同学可以看这里简单说来,笛卡尔树的一个子树可以代表一个区间,且左子树上点的下标小于根节点,右子树上点的坐标大于根节点。这道题要求所有子区间的\(\texttt{min}\)值之和,其实......
  • 迟钝的舞会 题解
    题目id:1329题目描述牛是公认的笨拙的舞者。然后,约翰发现富有音乐细胞的母牛能产更多的奶。因此,他把他的整圈的牛都拉进了舞蹈培训班,包括所有的公牛(因为跳舞的时候得一男一女-_-)。这些牛正好有\(n\)头是公的,有\(n\)头是母的。在第一堂课开始之前,舞蹈老师想将他们分成一对一对的(......
  • 08-04 题解
    08-03题解A根据题目的提示,发现所有数的积是不变的(\(gcd(a,b)*lcm(a,b)=a*b\)),所以差大和大简易证明设\(g=gcd(a,b)\),则\(a=a'g,\)\(b=b'g\),\(lcm(a,b)=a'b'g\)\(gcd(a,b)+lcm(a,b)=g(1+a'b')\)\(a+b=g(a'......
  • 08-02 题解
    <head><scriptsrc="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"type="text/javascript"></script><scripttype="text/x-mathjax-config">MathJax.Hub.Co......