【解题报告】CF DIV2 #ROUND 707 A~C

【解题报告】CF DIV2 #ROUND 707 A~C

比赛链接
半夜开比赛容易吵到室友所以以后开虚拟场了,这场还好没有贪心没在前3题,对我这种蒟蒻来说再好不过了。虽然还是只过了两题,不过A的还算快刚开始冲了一波2000名,然后卡死在第三题。

A.Alexey and Train

思路
模拟题,没啥好说的,看懂题目就可以了
代码

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;

/*DATA & KEY
t 1-100
n 1-100
a 1-1e6
tm 0-1e6


*/
int T;
const int N=105;
LL a[N],b[N],t[N];
void solve(int T)
{
	//NEW DATA CLEAN
	
	//NOTE!!!
	LL n;cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
	for(int i=1;i<=n;i++)cin>>t[i];
	
	LL arrive=0,depart=0,remain=0;
	for(int i=1;i<=n;i++)
	{
		arrive=depart+a[i]-b[i-1]+t[i];
		remain=(b[i]-a[i]+1)/2;
		depart=max(b[i],arrive+remain);
	}
	cout<<arrive<<endl;
}

int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

B.Napoleon Cake

思路
差分数组维护修改即可,不过注意可能超过边界即可
代码

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;

/*DATA & KEY
t 1 2e4
total n 1 2e5
ai 0 n
*/
int T;
const int N=2e5+10;
int d[N];
void solve(int T)
{
	//NEW DATA CLEAN
	memset(d,0,sizeof d);
	//NOTE!!!
	int n;cin>>n;
	for(int i=1,x;i<=n;i++)
	{
		cin>>x;//i-x+1~i
		d[max(1,i-x+1)]++;//max边界处理
		d[i+1]--;
	}
	int ans=0;
	for(int i=2;i<=n+1;i++)
	{
		ans+=d[i-1];
		if(ans>0)cout<<1<<" ";
		else cout<<0<<" ";
	}
	puts("");
}

int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

C.Going Home

题意
给最多2e5个数,每个数保证小于2.5*1e6问有没有符合 a [ x ] + a [ y ] = a [ w ] + [ z ] a[x]+a[y]=a[w]+[z] a[x]+a[y]=a[w]+[z]的四个不同的下标,
思路
这题比较有意思。原本以为二分+双指针什么的来优化,但是算来算去一直是时间复杂度爆炸的。
看了题解发现这玩意直接暴力出奇迹(没错,朴素的循环),不过暴力是有数学依据的:依据是鸽巢原理。
因为每个数保证小于 2.5 ∗ 1 e 6 2.5*1e6 2.51e6的,所以和最大也只有 5 e 6 5e6 5e6,也就是说如果用map存下来的话是很容易发生冲突碰到和相同的。时间复杂度约为 O ( m i n ( n 2 , 5 e 6 ) ) O(min(n^2,5e6)) O(min(n2,5e6)),直接暴力就完事了。

然而这玩意即使知道了这个也挺卡时间的hh

代码

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int>PII;
/*DATA & KEY
n 4 2e5
ai 1 2.5*1e6 
*/

int T;
const int N=2e5+10,M=5e6+10;
int a[N];
PII mp[M];
bool vis[M];
void solve()
{
	//NEW DATA CLEAN
	
	//NOTE!!!
	int n;scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
		{
			int v=a[i]+a[j];
			if(vis[v])
			{
				int x=mp[v].first,y=mp[v].second;
				if(x!=i&&y!=j&&x!=j&&y!=i)
				{
					puts("YES");
					printf("%d %d %d %d\n",i,j,x,y);
					return;
				}
			}
			else
			{
				mp[v]={i,j};
				vis[v]=1;
			}	
		}
	puts("NO");
}

int main()
{
	solve();
	return 0;
}

一个代码优化的点 , 别用stl用成憨憨了啊!

map<Type,int>mp/unordered_map<Type,int>mp
如果数据量小的话就直接用Type mp[N]

顺便map的count和find找的是key而不是对应的值

反思

A:

多模拟样例,自己造样例

B:

差分数组这种修改操作记得处理超过边界的非正常情况

C:

问一堆数字里是否能找出k个数满足一个等式。除了双指针,二分还要想到鸽巢原理+暴力。总之如果想不到策略那就来一发朴素暴力呗。暴力出奇迹!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值