CF1712

发布于 2022-08-14  261 次阅读


碎碎念

我输麻了QAQ

Day8

中午瞄了一眼,昨天打的div2,+251分

然后这是我打的第三把比赛,初始分是250分,呜呜呜呜呜

我的水平大概就1500了,寄

--------碎碎念到此结束,下面是正文(手动分割线)--------

别问,问就是没写,开摆

A - Wonderful Permutation

给你一个排列,每次可以任意交换两个数

询问多少次交换可以使sum[1..k]最小

solution

就是问你多少次交换能把数1-k挪到位置1-k上

#include<bits/stdc++.h>
using namespace std;
int T,n,k,ans,a[110];
int main()
{
	scanf("%d",&T);
	for(int i=1;i<=T;i++)
	{
		scanf("%d%d",&n,&k),ans=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=k+1;i<=n;i++)
			if(a[i]<=k)ans++;
		printf("%d\n",ans);
	}
	return 0;
}

B - Woeful Permutation

构造一个排列,使sum{lcm(i,ai)}最大

solution

每个数最优肯定是与它相差1的数

判断奇数和偶数的情况即可

#include<bits/stdc++.h>
using namespace std;
int T,n;
int main()
{
	scanf("%d",&T);
	for(int i=1;i<=T;i++)
	{
		scanf("%d",&n);
		if(n%2)
		{
			printf("1");
			for(int i=2;i<=n;i+=2)
				printf(" %d %d",i+1,i);
			printf("\n");
		}
		else
		{
			printf("2 1");
			for(int i=3;i<=n;i+=2)
				printf(" %d %d",i+1,i);
			printf("\n");
		}
	}
	return 0;
}

C - Sort Zero

给你一个数组,每次操作可以将所有等于x的元素设置成0

询问多少次操作可以让这个数组严格不降

solution

显然找末尾有多少不需要操作的元素即可

#include<bits/stdc++.h>
using namespace std;
int T,n,ans,nw,a[100010],s[100010];
int main()
{
	scanf("%d",&T);
	for(int _i=1;_i<=T;_i++)
	{
		scanf("%d",&n),ans=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]),s[i]=0;
		for(int i=1;i<=n;i++)
		{
			if(!s[a[i]])ans++;
			s[a[i]]++;
		}
		nw=a[n];
		for(int i=n;i>=1;i--)
		{
			if(a[i]==nw)
			{
				s[nw]--;
				if(!s[nw])ans--;
			}
			else
			{
				if(s[nw]||a[i]>nw)break;
				nw=a[i],s[nw]--;
				if(!s[nw])ans--;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

D - Empty Graph

给定一个数组,设置一个无限图,i->j的边权为min{a[i]...a[j]}

你可以进行k次操作,每次操作可以将一个数改为[1...10^9]的任意数

要求输出最大化的直径

solution

有两个(显然的?)性质:

  1. 两点间的最短路要么为 两点间直连的边长,要么为 两倍全局最小 a 的值;
  2. 图的直径必然可在相邻两点的最短路处取得;

然后可以用二分来检验每一次的答案

首先将所有能作为全局最小a的不合法的数修改,然后找一个最优的相邻两点修改

比较修改次数与k即可,好像还有贪心的做法,但是我赛时搞了两个小时没搞出来呜呜呜

#include<bits/stdc++.h>
#define MAXX 1000000000
using namespace std;
int T,n,k,a[100010];
int check(int p)
{
	int cnt=0,tag=2;
	for(int i=1;i<=n;i++)
	{
		if(a[i]*2<p)cnt++,tag=min(tag,1);
		if(a[i]>=p)tag=min(tag,1);
		if(i!=1&&(a[i-1]>=p||a[i-1]*2<p)&&(a[i]>=p||a[i]*2<p))tag=min(tag,0);
	}
	return cnt+tag<=k;
}
int main()
{
	scanf("%d",&T);
	for(int _i=1;_i<=T;_i++)
	{
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		int l=1,r=MAXX,ans=0;
		while(l<=r)
		{
			int mid=(l+r)/2;
			if(check(mid))
				ans=mid,l=mid+1;
			else r=mid-1;
		}
		printf("%d\n",ans);
	}
	return 0;
}