首页 > 其他分享 >Codeforces Round 814 (Div. 2)

Codeforces Round 814 (Div. 2)

时间:2023-12-14 11:46:45浏览次数:34  
标签:std maxx int Codeforces long tag cnt Div 814

基本情况

又是过了ABC。

A、B思路更多的是从数据上分析出来的,过的很顺。

C经典拿评测机来调试,甚至还RE了一次,最后终于过了。

C. Fighting Tournament

Problem - C - Codeforces

第一次改错

这题我的思路是找到规律后,优先队列加二分查找。

但是一直WA第二个点,这是我一开始的代码:

void solve()
{
	int n, Q, cnt = 0; std::cin >> n >> Q;
	int maxx = -1;
	for (int i = 1; i <= n; i++) std::cin >> a[i], maxx = std::max(maxx, a[i]);
	std::priority_queue<int,std::vector<int>,std::greater<int>> q;
	q.push(a[1]);
	for (int i = 2; i <= n; i++)
	{
		cnt++;
		q.push(a[i]); 
		tag[q.top()].push_back(cnt);
		q.pop();
		if (q.top() == maxx) break;	
	}
	while(Q--)
	{
		int u, k; std::cin >> u >> k;
		if (k >= cnt)
		{
			if (a[u] == maxx) std::cout << tag[a[u]].size() + k - cnt + 1;
			else std::cout << tag[a[u]].size() ;
		}	
		else
		{
			auto p = std::lower_bound(tag[a[u]].begin(), tag[a[u]].end(), k);
			std::cout << (p - tag[a[u]].begin()) + 1;
		}
		std::cout << std::endl;
	}
}

可以说是漏洞满篇,第一次改错我发现了一下几个问题(可恶的是样例都没卡掉)

  • tag[a[u]].size() + k - cnt

    • 这个结果是可能爆 int
    • 前面加上 long long 强转
  • tag[q.top()].push_back(cnt);

    • 这个点是我造了一组数据才发现的,(样例到底怎么过的?)。

    • 经典胡言乱语,我这里开的是小优先的优先队列,明明队首是小的,而这里想要的是记录胜者的场次。

    • 语句调换一下,先 pop 再剩下的 top 就是最大的了。

    • q.push(a[i]); q.pop();
      tag[q.top()].push_back(cnt);
      

然而提交后还是WA on test 2

第二次改错

void solve()
{
	int n, Q; std::cin >> n >> Q;
	long long cnt = 0;
	int maxx = -1;
	for (int i = 1; i <= n; i++) std::cin >> a[i], maxx = std::max(maxx, a[i]), tag[i].clear();
	std::priority_queue<int,std::vector<int>,std::greater<int>> q;
	q.push(a[1]); 
	for (int i = 2; i <= n; i++)
	{
		cnt++;
		q.push(a[i]); q.pop();
		tag[q.top()].push_back(cnt);
		if (q.top() == maxx) break;	
	}
	while(Q--)
	{
		int u, k; std::cin >> u >> k;
		if (k >= cnt)
		{
			if (a[u] == maxx) std::cout << (long long) tag[a[u]].size() + k - cnt;
			else std::cout << tag[a[u]].size() ;
		}	
		else
		{
			auto p = std::lower_bound(tag[a[u]].begin(), tag[a[u]].end(), k);
			std::cout << (long long) (p - tag[a[u]].begin()) + 1;
		}
		std::cout << std::endl;
	}
}

还是通过造数据找到的问题。

lower_bound 我下意识的认为是找第一个小于等于 \(k\) 的位置了,(什么根据题目自适应),但实际上是找第一个大于等于 \(k\) 的位置啊!所以整个 else 都是错的,再改。

else
{
	auto p = std::lower_bound(tag[a[u]].begin(), tag[a[u]].end(), k);
	if (*p == k) std::cout << (long long) (p - tag[a[u]].begin()) + 1;
	else
	{
		if (p == tag[a[u]].begin()) std::cout << 0;
		else 
		{
			p--;
			std::cout << (long long) (p - tag[a[u]].begin()) + 1;
		}
	}
}

然后RE了。

第三次改错

这个时候思路就比较清晰了,因为RE大概率就是迭代器操作的问题,然后我就发现要是没找到怎么办

比如我要查询的数据是第 \(7\) 轮,总共比了 \(9\) 轮,所以不会被上面那个 if 处理,而是转到了 else

然而查询的这个人最后赢得是第 \(5\) 轮,那么此时 lower_bound 是找不到第一个大于等于 7 的数的,它会返回 tag[a[u]].end()

其实到目前为止也没问题,因为我下面的算法已经让 p 自减了,算出来的正确性是可以保证的。

但是,我有一个语句是 if(*p == k) 而这里当 p = tag[a[u]].end() 的时候,显然会访问一个不确定的指针指向的值,这就导致了RE.

我是直接在这条语句上面加了特判来规避了RE,终于AC。

void solve()
{
	int n, Q; std::cin >> n >> Q;
	long long cnt = 0;
	int maxx = -1;
	for (int i = 1; i <= n; i++) std::cin >> a[i], maxx = std::max(maxx, a[i]), tag[i].clear();
	std::priority_queue<int,std::vector<int>,std::greater<int>> q;
	q.push(a[1]); 
	for (int i = 2; i <= n; i++)
	{
		cnt++;
		q.push(a[i]); q.pop();
		tag[q.top()].push_back(cnt);
		if (q.top() == maxx) break;	
	}
	while(Q--)
	{
		long long u, k; 
		std::cin >> u >> k;
		if (k >= cnt)
		{
			if (a[u] == maxx) std::cout << (long long) tag[a[u]].size() + k - cnt;
			else std::cout << tag[a[u]].size() ;
		}	
		else
		{
			auto p = std::lower_bound(tag[a[u]].begin(), tag[a[u]].end(), k);
			if (p == tag[a[u]].end()) std::cout << tag[a[u]].size();
			else if (*p == k) std::cout << (long long) (p - tag[a[u]].begin()) + 1;
			else
			{
				if (p == tag[a[u]].begin()) std::cout << 0;
				else 
				{
					p--;
					std::cout << (long long) (p - tag[a[u]].begin()) + 1;
				}
			}
		}
		std::cout << std::endl;
	}
}

标签:std,maxx,int,Codeforces,long,tag,cnt,Div,814
From: https://www.cnblogs.com/kdlyh/p/17900877.html

相关文章

  • CF301D Yaroslav and Divisors
    因为是排列,所以数对总数是调和级数的\(O(n\logn)\),可以暴力枚举。容斥,区间左右端点均在\([l,r]\)中的数对数量等于左右端点均在\([1,r]\)中的数对数量减去左右端点均在\([1,l-1]\)中的数对数量,再减去左端点在\([1,l-1]\)中且右端点在\([l,r]\)中的数对数量。发现前......
  • Codeforces Round 812 (Div. 2)
    基本情况第一次赛时做出div2的ABC。然而B题是秒的最快的?A题卡了一段时间经典+4,C题代码实现卡了一段时间。A.TravelingSalesmanProblemProblem-A-Codeforces卡题分析主要原因在少了特判,没有自己多构造几个特殊情况数据。这是一开始的代码voidsolve(){ intn,......
  • Codeforces Round 810 (Div. 2)
    基本情况A题秒了,B、C题死活看不懂题目。B.PartyProblem-B-Codeforces错误分析为啥看不懂题目,一方面是英语水平确实不够,另一方面就是图的意识不行,如果能看出来这题隐含的建图思想,就很有助于理解题目。正确思路题意有\(T\)组数据,每组数据给你一组\(n,m\)表示共......
  • [Codeforces] CF1737C Ela and Crickets
    CF1737CElaandCrickets题意给定一个\(n\timesn\)的棋盘,棋盘上有且仅有三颗排成\(\text{L}\)形的棋子。对于\(\text{L}\)形的定义,有且仅有以下四种情况:棋子的移动规则和跳棋相同。它可以水平、垂直或斜向移动。当且仅当一个棋子的某个方向紧随另一个棋子时,它能跳......
  • [ARC133B] Dividing Subsequence
    DividingSubsequence这道题与最长公共子序列类似,可以先去水一水那道题。题意本题就是让你从\(p\)里面选出一个子序列\(b_i\)和\(q\)里面选出一个子序列\(a_i\),我们要使\(b_i\)是\(a_i\)的倍数。解法本题直接用动态规划,是\(O(n^2)\)做法,会超时,因此我们用树状数......
  • Codeforces Round 809 (Div. 2)
    基本情况A题秒了。B题卡了很久,最后过了。C来不及了。B.MakingTowersProblem-B-Codeforces卡题分析最初想法其实已经推出来下标差为奇数才能构成高塔了。但是思维固化,认为这个问题就必须用LIS那类做法做,然后硬打了一个\(\operatornameO(n^2)\)的DP,然后就TLE......
  • Codeforces Round 808 (Div. 2)
    基本情况最难受的一集。A搞了一个半小时愣是没开出来。A.DifferenceOperationsProblem-A-Codeforces错误分析我分了好多类讨论,换言之没找到更本质的东西。我想的是如果前面有一个数能处理到\(1\)那后面就都能过。止步于此,而没有往更本质,更普适的地方想。然后又......
  • Codeforces Round 807 (Div. 2)
    基本情况AB题秒了。C题搞了半天,搞了一个假的解法,最后还是爆空间了。D题没想下去。C.MarkandHisUnfinishedEssayProblem-C-Codeforces错误分析写出来自己的错解之后没有进一步思考,而是觉得没希望直接做D去了,实则D也没可能半小时写完。我的错解就是预处理好每个......
  • Codeforces 198 B Jumping on Walls
    题面翻译题目描述瓦西亚在和忍者玩电脑游戏。在这个关卡,瓦西亚需要操控忍者走出一个很深的峡谷。峡谷由两面垂直于地面且互相平行的墙组成,它们的高度为\(n\)米。我们将这些墙分成许多\(1\)米长的区域,并从下到上用\(1\)到\(n\)的正整数对它们进行编号。有些地方是安全的,忍者可以......
  • Codeforces Round 914 (Div. 2)
    基本情况A题+2,幸好后面突然悟了。B题体现了读题以及一词多义的重要性。C题不会。看了一下1700分的题目,暂时先放了。A.TheThirdThreeNumberProblemProblem-A-Codeforces推出了规律,\(n\)为偶数的时候,无脑\(a=n\oplus1,b=n\oplus1,c=1\)就行。然而奇数......