3.24 CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes)小结

19 篇文章 0 订阅
17 篇文章 0 订阅

        这次心态给我打崩了,还是不太适应这种偏向数学的思维题,或者说还是太菜了。确实还得多练练。这次只出了,一道A(还因为设置无穷大的值太小卡了好几次),第二题公式关系一直推错。别的题基本没时间看,挺受打击的。因为赛后来看这两题真的不难,卡了一个多小时真不应该。

A题

大意是,对一个给定长度为n的数列a,必定存在一个数对<i,j>(1<=i,j<=n)使a[i],a[j]对任意k(1<=k<=n)都满足

其中,i 和 j 可以相等 找出其中一个满足这个条件的<i,j>对

思路

不得不说挺虎人的,没经验的我我还一直想化成二维平面用几何关系解题。实际是就讨论绝对值,把绝对值消了,抵消难以讨论的a[k]就行。

要消去a[k],就得左边的两个绝对值都不改变原式符号,或者都改变原式符号。之后就很显然了,如果都不改变符号,说明ai-ak>=0,也就是 ai 是整个数列的最大值,ak-aj>=0,说明aj是整个数列的最小值,自然而然,右边式子ai-aj也不改变符号,ak抵消,此时左边式子等于右边式子。

同理可得左边两个绝对值都改变符号的情况。

所以思路就很简单了,去找数列的最大值和最小值的位置就行。

代码实现

#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int t,n;
int main()
{
	ios::sync_with_stdio(false); cout.tie(NULL);
	cin >> t;
	while (t--) {
		cin >> n;
		vector<int>arr(n);
		ll mx = -999999999999, mn = 999999999999;
		int p1 = 1, p2 = 1;
	
		for (int j = 0; j < n; j++) {
			ll t;
			cin >> t;
			arr[j] = t;
			if (t > mx) {
				mx = t;
				p1 =j+1;
			}
			if (t < mn) {//找极值,并更新位置
				mn = t;
				p2 = j+1;
			}
		}
		cout << p1<< " " << p2 << endl;
	}
 
	return 0;
}

B题 

大意,给定一个长度为n 的数列和目标值 k,每次删除其中的一个元素x,同时所有剩余元素都减去x,执行n-1次操作后,判断最后剩下的这个元素是否为 k,是的话输出 YES,否则输出 NO

思路:

最简单是思路就是遍历加模拟,但这个模拟减数的过程可以被数学归纳O(1)概括,所以我们就去找去一个数学关系,遍历每一个数,如果这个数和k满足这个关系就输出YES,如果遍历完还没找到就输出NO。

然后就是这个规律的推导

设 a1,a2…an-1,an 中ai (1<=i<=n-1)表示第i个被删除的元素
第一次操作:
        剩余 {b2…bn-1,bn},b2=a2-a1 , bn-1=an-1 - a1 , bn=an-a1

第二次操作

         剩余 {c3…cn-1,cn},c3=b3-b2 , cn-1=bn-1 - b1 , cn=bn - b1

....

n-2次操作后得到

        剩余{a’n-1,a'n} 

n-1次操作后

        剩余{a''n} a''n=a'n-a'n-1;

联立所有式子消项得到a '' n= an -an-1

要使a '' n=k,所以an - an-1 要等于 k,条件也就变成了最后删除的元素 an-1,an + k=an-1

an-1也是原数列的元素,所以只要an-1存在就会满足题目的条件。

所以我们可以使用multiset来存元素,因为不知道最后一个删除的元素是谁,我们就遍历一遍原数组,如果满足Set.find(arr[j]+k)存在就输出YES

代码实现

#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#define ll long long

using namespace std;

int t, n, k;
ll sum1 = 0, sum2 = 0;
int main()
{
	ios::sync_with_stdio(false); cout.tie(NULL);


	cin >> t;
	while (t--) {
		cin >> n >> k;

		vector<int>arr(n);
		multiset<int>s;
		for (int j = 0; j < n; j++) {
			int t;
			cin >> t;
			arr[j] = t;
			s.insert(t);
		}
		int j = 0;
		for (j = 0; j < n; j++) {
			if (s.find(arr[j]+k) !=s.end())//关键式子
			{
				cout << "YES" << endl;
				break;
			}
		}
		if (j >= n) {

			cout << "NO" << endl;
		}


	}
	return 0;
}

先更这两个,再补会题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值