CF1041

A.Heist

CF原题链接

题目大意:

给出一个长度为n的序列a,已知序列a是由一个首项为x、常数为1的等差数列删除若干个数得来,求删数的最少个数。

解题思路:

直接做做完了啊,为什么这题不是红题 既然要让删的数最少,那就要让原序列长度尽量小。我们钦定首项xmina,末项为maxa,然后给原序列升序排序,Σi=2n(aiai11)就是答案。

没啥用的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010;
int n,a[N];
int ans;

signed main()
{
	scanf("%lld",&n);
	for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
	sort(a+1,a+1+n);
	for (int i=2;i<=n;i++) ans+=a[i]-a[i-1]-1;
	printf("%lld",ans);
	return 0;
}

B.Buying a TV Set

CF原题链接

题目大意:

给出4个数a,b,c,d,求满足xy=cd,xa,yb(x,y)数量。

解题思路:

直接做做完了啊,为什么这题不是红题 容易想到,有一种东西叫做约分。那么我们钦定cd是最简分数(不是的话就给它约分一下),那么x,y一定分别是c,d的倍数。然后就出来了,答案就是min(ac,bd)

没啥用的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c,d;

int gcd(int x,int y)
{
	if (y==0) return x;
	return gcd(y,x%y);
}
signed main()
{
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
	int gd=gcd(c,d);
	c/=gd,d/=gd;
	printf("%lld",min(a/c,b/d));
	return 0;
}

C.Coffee Break

CF原题链接

题目大意:

给出n,m,d与一个长度为n的序列a,每次删除操作可以从a中删除若干个数del,使得这些数升序排序后delideli1>d。求最少删除完整个序列a的操作次数,与每个数是在第几个操作删除的。(1n2×105,1dm109)

解题思路:

注意到时限为2s。记录序列a时顺便记录位置,然后升序排序a。可以想到对于ai它一定可以影响到aj满足aj>ai+d,那么对于每个ai二分查找第一个aj并标记(每次查找一个即可),若当前ai未被标记,说明需要一个新的操作,此时cnt++即可。

不做评价的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,d;
struct node{
	int x,d;
	int used;
	bool operator < (const node &b) const{
		return x<b.x;
	}
}a[N];
int cnt;
int ans[N];

signed main()
{
	scanf("%lld%lld%lld",&n,&m,&d);
	for (int i=1,x;i<=n;i++)
	{
		scanf("%lld",&a[i].x);
		a[i].d=i;
	}

	sort(a+1,a+1+n);
	for (int i=1;i<=n;i++)
	{
		if (a[i].used==0) a[i].used=++cnt;//没被选过,一定要加 
		ans[a[i].d]=a[i].used;
		int p=lower_bound(a+1,a+1+n,(node){a[i].x+d+1,0,0})-a;
		while (a[p].used&&p<=n) p++;//寻找下一个未操作过的a[p]
		if (p>n) continue;
		a[p].used=a[i].used;
	}

	printf("%lld\n",cnt);
	for (int i=1;i<=n;i++) printf("%lld ",ans[i]);
	return 0;
}

D.Glider

CF原题链接

题目大意:

可恶的翻译为什么不说输入不相交且是升序排列亏得我还想树状数组维护区间

给定高度hn个区间[l,r],保证区间不相交且升序输入。在区间外每过一个单位长度,高度就会下降一个单位长度,在区间内高度不变 请想象原神的风之翼与风场。求能飞的最远距离(1n2×105,1h109)

解题思路:

贪心地想,优的方案一定是从某个风场区间的左端点开始飞,所以枚举左端点,预处理出下降高度的前缀和,每次二分查找就行。

但是要注意前缀和乱七八糟的细节问题。

不做评价的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,h;
int l[N],r[N],sum[N];
int ans;

signed main()
{
	scanf("%lld%lld",&n,&h);
	for (int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&l[i],&r[i]);
		sum[i]=sum[i-1]+l[i]-r[i-1];//到第i个区间下降总高度的前缀和
	}
	for (int i=1;i<=n;i++)
	{
		int p=lower_bound(sum+1,sum+1+n,sum[i]+h)-sum-1;
		ans=max(ans,r[p]-l[i]+(h+sum[i]-sum[p]));
	}
	printf("%lld",ans);
	return 0;
}

E.Tree Reconstruction

CF原题链接

题目大意:

给出n,表示有一棵有n个节点的树,给出每条树边被删除后两个联通块中编号最大的两个结点x,y,要求构造出满足条件的树,输出树边(2n1000)

解题思路:

小清新构造题。

可以想到,对于给出节点x,y 一定存在x=ny=n(因为n节点一定会是左联通块或右联通块中最大的),若存在一组xnyn那么一定无法构造。

我们可以构造一条链,这样所有x就相当于这条链上的前缀最大值(我们使x是另一个联通块的最大值)。将所有x排序,然后构造就行,无法构造就输出NO

为什么无法构造链就一定无法构造出满足要求的树呢?感性理解

虚空调试小技巧:双重循环全是i

难以描述的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010;
int n;
int a[N];
bool flag[N];
int ans[N];

signed main()
{
	scanf("%lld",&n);
	for (int i=1,aa,b;i<n;i++)
	{
		scanf("%lld%lld",&aa,&b);
		if (aa>b) swap(aa,b);
		if (b!=n) { printf("NO"); return 0; }
		a[i]=aa;
	}
	sort(a+1,a+n);
	for (int i=1;i<=n;i++)
	{
		if (a[i]!=a[i-1]) 
		{
			ans[i]=a[i];
			flag[a[i]]=true;
			continue;
		}
		bool o=false;
		for (int j=1;j<=a[i];j++)
		{
			if (!flag[j]) 
			{
				ans[i]=j;
				flag[j]=true;
				o=true;
				break;
			}
		}
		if (!o) {  printf("NO"); return 0;  }
	}
	ans[n]=n;
	printf("YES\n");
	for (int i=1;i<n;i++) printf("%lld %lld\n",ans[i],ans[i+1]);
	return 0;
}

F.Ray in the tube

CF原题链接
不会不会


posted @   还是沄沄沄  阅读(81)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示