Codeforces Round #719 (Div. 3) A B C D E F题解

A. Do Not Be Distracted!

题意

给定一个字符串,每种字母表示一种任务,请问任务是否连续完成,没有分开

思路

  • 暴力统计,一旦任务断开就标记,再出现就结束

时间复杂度

O(T*n)

参考代码

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#define max(a,b) (a>b?a:b)
using namespace std;
int t,n,cnt[500]; 
string s;
int main(){
	scanf("%d",&t);
	while(t--){
		memset(cnt,0,sizeof(cnt));
		scanf("%d",&n);
		cin>>s;
		int ans=0;
		for(int i=1;i<n;i++){
			if(s[i]!=s[i-1]){
				if(cnt[s[i-1]]!=0)
					ans=1;
				cnt[s[i-1]]++;
			}
		}
		if(cnt[s[n-1]]!=0)
			ans=1;
		printf("%s\n",ans?"NO":"YES");
	}
	
}

 

B. Ordinary Numbers

题意

对于n,请问[1,n]中有多少个所有数码都一样的数字(如2,55,888)

思路

  • 暴力统计,将所有数字预处理,直接统计即可

时间复杂度

O(T*大常数)

参考代码

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int t,n;

int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		int ans=0;
		if(n>=1) ans++;
		if(n>=2) ans++;
		if(n>=3) ans++;
		if(n>=4) ans++;
		if(n>=5) ans++;
		if(n>=6) ans++;
		if(n>=7) ans++;
		if(n>=8) ans++;
		if(n>=9) ans++;
		if(n>=11) ans++;
		if(n>=22) ans++;
		if(n>=33) ans++;
		if(n>=44) ans++;
		if(n>=55) ans++;
		if(n>=66) ans++;
		if(n>=77) ans++;
		if(n>=88) ans++;
		if(n>=99) ans++;
		if(n>=111) ans++;
		if(n>=222) ans++;
		if(n>=333) ans++;
		if(n>=444) ans++;
		if(n>=555) ans++;
		if(n>=666) ans++;
		if(n>=777) ans++;
		if(n>=888) ans++;
		if(n>=999) ans++;
		if(n>=1111) ans++;
		if(n>=2222) ans++;
		if(n>=3333) ans++;
		if(n>=4444) ans++;
		if(n>=5555) ans++;
		if(n>=6666) ans++;
		if(n>=7777) ans++;
		if(n>=8888) ans++;
		if(n>=9999) ans++;
		if(n>=11111) ans++;
		if(n>=22222) ans++;
		if(n>=33333) ans++;
		if(n>=44444) ans++;
		if(n>=55555) ans++;
		if(n>=66666) ans++;
		if(n>=77777) ans++;
		if(n>=88888) ans++;
		if(n>=99999) ans++;
		if(n>=111111) ans++;
		if(n>=222222) ans++;
		if(n>=333333) ans++;
		if(n>=444444) ans++;
		if(n>=555555) ans++;
		if(n>=666666) ans++;
		if(n>=777777) ans++;
		if(n>=888888) ans++;
		if(n>=999999) ans++;
		if(n>=1111111) ans++;
		if(n>=2222222) ans++;
		if(n>=3333333) ans++;
		if(n>=4444444) ans++;
		if(n>=5555555) ans++;
		if(n>=6666666) ans++;
		if(n>=7777777) ans++;
		if(n>=8888888) ans++;
		if(n>=9999999) ans++;
		if(n>=11111111) ans++;
		if(n>=22222222) ans++;
		if(n>=33333333) ans++;
		if(n>=44444444) ans++;
		if(n>=55555555) ans++;
		if(n>=66666666) ans++;
		if(n>=77777777) ans++;
		if(n>=88888888) ans++;
		if(n>=99999999) ans++;
		if(n>=111111111) ans++;
		if(n>=222222222) ans++;
		if(n>=333333333) ans++;
		if(n>=444444444) ans++;
		if(n>=555555555) ans++;
		if(n>=666666666) ans++;
		if(n>=777777777) ans++;
		if(n>=888888888) ans++;
		if(n>=999999999) ans++;
		printf("%d\n",ans);
	}
}

 

C. Not Adjacent Matrix

题意

对于n,请将1到n*n的数字填到n*n的矩阵当中,使得相邻位置的元素都不相邻,无解输出-1

思路

  • n=1,直接输出即可
  • n=2,无解
  • 将格子分奇偶,行列之和奇数的从上到下先填,剩下的后填,就可以满足题目要求

时间复杂度

O(T\times n^2)

参考代码

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#define max(a,b) (a>b?a:b)
using namespace std;
int t,n,ans[110][110]; 
string s;
int main(){
	scanf("%d",&t);
	while(t--){
		memset(ans,0,sizeof(ans));
		scanf("%d",&n);
		if(n==1){
			printf("1\n");
			continue;
		}
		if(n==2){
			printf("-1\n");
			continue;
		}
		int cnt=0;
		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if((i+j)&1) ans[i][j]=++cnt;
		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(ans[i][j]==0) ans[i][j]=++cnt;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++) 
				printf("%d ",ans[i][j]);
			printf("\n");
		} 
	}
	
}

 

D. Same Differences

题意

对于数组A,请问多少对数满足a_i-a_j=i-j

思路

  • 首先进行移项,原式即为a_i-i=a_j-j
  • 不难发现,式子具有传递性,用map统计集合即可得到集合大小
  • ans=\sum \frac{size*(size-1)}{2}

时间复杂度

O(T\times nlogn)

参考代码

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int t,n;

int main(){
	scanf("%d",&t);
	while(t--){
		map<int,int> mp;
		scanf("%d",&n);
		for(int i=1,x;i<=n;i++){
			scanf("%d",&x);
			mp[x-i]++;
		}
		long long ans=0;
		map<int,int>::iterator iter;
    	iter = mp.begin();
    	while(iter != mp.end()){
    		long long cnt=iter->second;
    		ans+=(cnt*(cnt-1))/2;
    		iter++;
		}
		printf("%lld\n",ans);
	}
}

 

E. Arranging The Sheep

题意

有一群羊在一条线上,每次可以让一头左移或者右移一个单位,最少多少次能够把羊聚在一起(必须全部连续)

思路

  • 首先假设最优位置是pos,则我们需要:将左边的羊聚过来,将右边的羊聚过来
  • 首先可以做前缀和,后缀和,搞清前后一共有多少羊
  • 计算左边/右边羊聚过来的代价,如果这里有羊,不用管它,否则增加一下代价
  • 尝试枚举每个位置,注意:如果这里没有羊,可以让左边或者右边的退一步

时间复杂度

O(T*n)

参考代码

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#define max(a,b) (a>b?a:b)
using namespace std;
const int maxn=1e6+10;
int t,n,pre[maxn],after[maxn]; 
long long prea[maxn],aa[maxn];
string s;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		cin>>s;
		s=" "+s;
		for(int i=1;i<=n;i++) pre[i]=pre[i-1]+(s[i]=='*');
		after[n+1]=0;
		for(int i=n;i>=1;i--) after[i]=after[i+1]+(s[i]=='*');
		for(int i=1;i<=n;i++)
			if(s[i]=='*') 
				prea[i]=prea[i-1];
			else
				prea[i]=prea[i-1]+pre[i-1];
		aa[n+1]=0;
		for(int i=n;i>=1;i--)
			if(s[i]=='*') 
				aa[i]=aa[i+1];
			else
				aa[i]=aa[i+1]+after[i+1];
		long long ans=1;
		ans<<=60;
		for(int i=1;i<=n;i++){
			long long poss=0;
			if(s[i]=='*') ans=min(ans,prea[i]+aa[i]);
			else ans=min(ans,prea[i]+aa[i]-max(pre[i],after[i]));
		}
		printf("%lld\n",ans);
	}
	
}

 

F1. Guess the K-th Zero (Easy version)

题意

长度为n的数组,元素为0或1,有20次询问区间和的机会,求第k个0在那个位置

思路

  • 每次询问1-x的前缀和,二分即可得到答案

询问次数

log_2N\leqslant 20

参考代码

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int t,n,k;

int main(){
	scanf("%d%d%d",&n,&t,&k);
	int cnt=20,l=1,r=n;
	while(cnt--){
		if(l>r) break;
		int mid=(l+r)>>1;
		printf("? %d %d\n",1,mid);
		fflush(stdout);
		int x;
		scanf("%d",&x);
		if(x+k<=mid){
			r=mid-1;
		}else{
			l=mid+1;
		}
	}
	printf("! %d",r+1);
	fflush(stdout);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值