CF1506

感觉今天脑子特别不清醒AWA

A.Strange Table

CF原题链接

题目大意:

给出两种矩阵的排列方式:

  • 竖排

147101325811143691215

  • 横排

123456789101112131415

每次给出n,m,k,求在n×m的矩阵中,对于竖排数字为k的位置,横排数字是多少(1n,m106,1kn×m)

解题思路:

直接做做完了。通过一些加减乘除求出数字k在竖排中的位置坐标(x,y),再通过一些加减乘除求出横排中(x,y)的数即可。

可恶啊,刚开始取模的时候没特判0

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
int T;
int n,m,x;
signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld%lld%lld",&n,&m,&x);
		int r=x%n,c=(x+n-1)/n;
		if (r==0) r=n;
		printf("%lld\n",(r-1)*m+c);
	}
	return 0;
}

B.Partial Replacement

CF原题链接

题目大意:

给出一个由' . '和' * '组成的字符串s,每次操作需要将一个' * '改为' x ',使得对于所有si=sj=x ,满足jik

特别地,要求第一个与最后一个' * '必须变为' x '。

求使字符串满足条件时,最少的操作次数。保证给出数据有合法解。(1kn500)

解题思路:

直接模拟做做完了。用pre记录上一个变为' x '的位置,用lst记录上一个' * '的位置,若当前ipre>k,那么lst就一定要变成' x '。注意特判第一个和最后一个,额外+1的时候不要重复加。

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
int T;
int n,k;
string str;
int cnt,tol;

signed main()
{
	cin>>T;
	while (T--)
	{
		cin>>n>>k>>str;
		cnt=tol=0;
		int _size=str.size();
		int pre=-1,lst=0;
		for (int i=0;i<_size;i++)
		{
			if (str[i]!='*') continue;
			if (pre==-1) lst=i;
			if (i-pre>k||pre==-1) cnt++,pre=lst;
			lst=i,tol++;
		}
		if (tol>1) cnt++;
		printf("%lld\n",cnt);
	}
	return 0;
}

C.Double-ended Strings

CF原题链接

题目大意:

给出两个字符串a,b,每次操作可以删去一个字符串的第一个字符或最后一个字符,求至少需要多少次操作可以使得a,b完全相同。(1|a|,|b|20)

解题思路:

逆转题意,我们可以将题意转化为:求a,b的最长公共子串长度len,输出|a|+|b|len×2。注意到极小的数据量,我们可以直接设状态fi,j表示以ai,bj结尾的最长公共子串的长度,状态转移方程也很好想,就是

fi,j={0,aibjfi1,j1+1,ai=bj

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=25;
int T;
string a,b;
int f[N][N];
int ans;

signed main()
{
	cin>>T;
	while (T--)
	{
		cin>>a>>b;
		int size1=a.size(),size2=b.size();
		a=" "+a,b=" "+b;
		ans=0;
		for (int i=1;i<=size1;i++)
		{
			for (int j=1;j<=size2;j++)
			{
				if (a[i]==b[j]) f[i][j]=f[i-1][j-1]+1;
				else f[i][j]=0;
				ans=max(ans,f[i][j]);
			}
		}
		cout<<size1+size2-ans*2<<'\n';
	}
	return 0;
}

D.Epic Transformation

CF原题链接

题目大意:

给出一个长度为n的序列a,每次操作可以选择i,j 满足aiaj并删除ai,aj,求序列a经过若干次操作后最少有多少个数。(1Σn2×105,1ai109)

解题思路:

注意到什么情况下会剩下数。设k为序列中值为某数的个数,只要kn2那么一定有法两两匹配;但若是存在k>n2,那么一定会剩下 k×2n 个数无法匹配。显然,这样的数在整个序列中最多只会存在一个,所以统计最大的k值即可。再次注意到ai的值域,再次用map当桶数组。

注意到两两匹配,那么还需要判断一下n的奇偶再输出。

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int T;
int n,a[N];
map <int,int> bx;
int k;

signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		k=0;
		bx.clear();
		scanf("%lld",&n);
		for (int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			bx[a[i]]++;
			k=max(k,bx[a[i]]);
		}
		if (k<=n/2) printf("%lld\n",n%2);
		else printf("%lld\n",k*2-n);
	}
	return 0;
}

E.Restoring the Permutation

CF原题链接

题目大意:

给出一个长度为n的序列q,要求分别输出字典序最小、字典序最大的合法排列p。我们认为排列p合法,当且仅当:

  • p是长度为n的排列
  • 对于i[1,n],有qi=max{p1,p2,,pi}

(1n2×105,1qin)

解题思路:

翻译题意后,原题相当于:给出一个排列的前缀最大值数组q,要求输出字典序最大、最小的原排列p

直接模拟做完了。用set维护剩下可选的数,若qiqi1,那么一定满足pi=qi;若qi=qi1,那么贪心考虑pi即可。

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int T;
int n,q[N];
int ans1[N],ans2[N];
set <int> st1,st2;

signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld",&n);
		for (int i=1;i<=n;i++) scanf("%lld",&q[i]);
		
		for (int i=1;i<=n;i++) st1.insert(i),st2.insert(i);
		for (int i=1;i<=n;i++)
		{
			if (q[i]!=q[i-1]) 
			{
				ans1[i]=ans2[i]=q[i];
				st1.erase(q[i]),st2.erase(q[i]);
				continue;
			}
			set <int> ::iterator it=st2.lower_bound(q[i]);
			it--;
			ans2[i]=*it;
			st2.erase(*it);
			set <int> ::iterator it2=st1.begin();
			ans1[i]=*it2;
			st1.erase(*it2);
		}
		
		for (int i=1;i<=n;i++) printf("%lld ",ans1[i]);
		printf("\n");
		for (int i=1;i<=n;i++) printf("%lld ",ans2[i]);
		printf("\n");
	}
	return 0;
}

F.Triangular Paths

CF原题链接

题目大意:

考虑一个多层三角形,第k层有k个节点,层数从1开始标号。对于节点(r,c),它分别有一条连向(r+1,c),(r+1,c+1)的边。若r+c是偶数,那么到(r+1,c)的边是有效边,否则到(r+1,c+1)的边有效。

一开始在位置(1,1),每次操作可以通过有效边到达下一层,或耗费1的代价,使得对于节点(r,c),原本有效边变无效、原本无效边变有效。

现在给出n个点的标号(ri,ci),要求输出可以全部经过这些点的最小大家。(1Σn2×105,1ciri109)

解题思路(口胡):

原题的图不助于理解题意,于是有了下图。

容易发现,原本的图形成了若干个不相交的子图,而同一个子图中rc2相等。在一个子图中,在左边的节点可以直接走到,在右边的需要代价,那么分类讨论一下。

若点(r,c)满足r+cmod2=0,那么这个点一定需要一定代价才能走到,统计需要新建的边即可。

若点(r,c)满足r+cmod2=1,那么它通过一些新建的边到达它所在的子图即可,统计它所在子图所需的代价即可。

posted @   还是沄沄沄  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示