Codeforces Round 970 (Div. 3)(ABCDEF)

Codeforces Round 970 (Div. 3)

A:Sakurako's Exams

签到

题意:给定1,2的数量,判断是否能用加减符号使得这些1,2计算出0

cpp 复制代码
void solve()
{
	cin>>n>>m;
	if(n%2)cout<<"NO\n";
	else
	{
		if(m%2==0||n)cout<<"YES\n";
		else cout<<"NO\n";
	}
	return ;
}

B:Square or Not

签到

题意:给定01序列,问从上到下,从左到右排列是否可以得到一个周围为1,内部为0的正方形

cpp 复制代码
void solve()
{
	string s;
	cin>>n;
	cin>>s;
	int t=sqrt(n);
	if(t*t!=n)
	{
		cout<<"No\n";
		return;
	}
	else 
	{
		int idx=0;
		for(int i=0;i<t;i++)
		{
			for(int j=0;j<t;j++)
			{
				int now=i*t+j;
				if(i==0||j==0||i==t-1||j==t-1)
				{
					if(s[now]=='0')
					{
						cout<<"No\n";
						return;
					}
				}
				else if(s[now]=='1')
				{
					cout<<"No\n";
					return;
				}
			}
		}
	}
	cout<<"Yes\n";
	return ;
}

C:Longest Good Arrays

题意:给定左右边界了l,r,问在范围内凑出最长的满足a[i]-a[i-1]<a[i+1]-a[i](i>=2)的最长数组的长度

思路:最优一定是前后两项差从左到右分别为1,2,3,4...,所以二分数组最后一个元素,满足小于r-l的第一个元素位置,再+1就是答案

cpp 复制代码
int n,m;
int cha;
bool check(int x)
{
	return (x+1)*x/2>cha;
}
void solve()
{
	cin>>n>>m;
	cha=m-n;
	int l=0,r=1e8;
	while(l+1<r)
	{
		int mid=l+r>>1;
		check(mid)?r=mid:l=mid;
	}
	cout<<l+1<<'\n';
	return ;
}

D:Sakurako's Hobby

题意:输入一个数组大小n,然后输入n个数q[i](1<=i<=n)代表i可以到达q[i](保证q数组一定是一个排列),然后输入一个01串,当第i个位置为'1'代表为白块,为'0'代表为黑块,f[i]为能够到达i这个点的所有黑块的数量,输出所有f[i](1<=i<=n)

例如:

输入

2

2 1

00

输出

2 2

(因为1位置的点都能由1,2到达)

思路:并查集,把所有有联系的点都缩到一个根上(由于是一个排列,所以所有可以直接可以到达或者间接到达的点都可以形成一个环,也就是相互到达),最后问f[i]只需要把一个环中的所有店都累加到find(i),也就是根节点上

代码:

cpp 复制代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e6+10,INF=4e18;
int n,m;
int f[N],q[N],cnt[N];
bool st[N];
int find(int x)
{
	if(x!=f[x])return f[x]=find(f[x]);
	return f[x];
}
void root(int a,int b)
{
	int x=find(a),y=find(b);
	if(x!=y)f[x]=y;
}
void solve()
{
	cin>>n;
	_rep(i,1,n)cin>>q[i],f[i]=i,st[i]=false,cnt[i]=0;
	string s;
	cin>>s;
	s=" "+s;
	_rep(i,1,n)
	{
		int now=i;
		while(!st[now])
		{
			st[now]=true;
			root(now,q[now]);
			now=q[now];
		}
	}	
    _rep(i,1,n)
		if(s[i]=='0')
			cnt[find(i)]++;
	_rep(i,1,n)
		cout<<cnt[find(i)]<<" ";
	cout<<'\n';
	return ;
}
signed main()
{
	IOS;
	int T=1;
	cin>>T;
	while(T--)
		solve();
	return 0;
}

E:Alternating String

题意:给定一个字符串,现在有两个操作

1:选一个字母删除(但是这个最多只能操作一次)

2:将一个位置的字母改成另一个字母

问你把这个字符串变成一个:奇数位置字母都相同,偶数位置字母都相同 的字符串的最小操作次数

思路

只要发现一个特点就可以想到这个思路,那就是当你选择把当前这个点i的字母删除之后,后面所有的字母所在的奇偶位置就发生了互换

1.首先考虑不删除字母的情况

维护一个hou[26][2]的数组,其中第一维代表哪个字母(0~25),第二维 0/1 代表 奇数位/偶数位

那么我首先遍历奇数位置的所有字母,求和sum就是奇数位置字母的数量,求最大值ma就是奇数位置 字母的众数那么sum-ma就是奇数位置最少需要改变的字母的数量

偶数位置同理,那么就能求导不删除字母情况下最小操作次数

2,考虑删除字母的情况

假如我现在删除的是i号点,那么1~i-1号点的奇偶性质未发生改变,那么我就从小到大遍历即可,i+1~n号点的奇偶性质全部发生了改变,那么显然如果我能预处理出i+1~n的所有状态,也就是前面说到的hou[26][2],那么奇数位本来是hou[0~25][0]现在只需要考虑hou[0~25][1],偶数位置同理,那么就可以发现这个hou[0~25][2]显然可以提前预处理出来,然后遍历到第i个点的时候把1~i的状态删去就行,这些都可以线性处理,时间复杂度O(26*n)

代码:

cpp 复制代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e6+10,INF=4e18;
int n,m;
int now[26][2],hou[26][2];//now储存1~i-1的状态,hou储存i+1~n的状态
void solve()
{
	cin>>n;
	string s;
	cin>>s;
	memset(now,0,sizeof(now));
	memset(hou,0,sizeof(hou));
	s=" "+s;
	_rep(i,1,n)
		hou[s[i]-'a'][i%2]++;
	int res=0,sum,ma;
	_rep(j,0,1)
	{
		sum=0;	
		ma=0;
		_rep(i,0,25)
		{
			sum+=hou[i][j];
			ma=max(hou[i][j],ma);
		}
		res+=sum-ma;
	}
	if(n%2)
	{
		res=INF;
		_rep(i,1,n)
		{
			int nowres=0;
			hou[s[i]-'a'][i%2]--;
			_rep(j,0,1)
			{
				sum=0;
				ma=0;
				_rep(k,0,25)
				{
					sum+=hou[k][j];
					sum+=now[k][j^1];
					ma=max(ma,hou[k][j]+now[k][j^1]);
				}
				nowres+=sum-ma;
			}
			now[s[i]-'a'][i%2]++;
			res=min(res,nowres+1);
		}
	}
	cout<<res<<"\n";
	return ;
}
signed main()
{
	IOS;
	int T=1;
	cin>>T;
	while(T--)
		solve();
	return 0;
}

F:Sakurako's Boxt

题意:给定一个数组,为元素之间两两相乘(a[1]*a[2]和a[2]*a[1]重复不算)的平均数是什么

思路:

假设四个元素

那么答案就是

等价于

用一个后缀和维护形如的东西这道题就轻松解决了,只需要注意一下取模和乘法逆元的问题就行了

cpp 复制代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e6+10,INF=4e18,P=1e9+7;
int n,m;
int hou[N],q[N];
int qmi(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)res=res*a%P;
		a=a*a%P;
		b>>=1;
	}
	return res;
}
void solve()
{
	cin>>n;
	_rep(i,1,n)cin>>q[i];
	hou[n+1]=0;
	_pre(i,n,1)
		hou[i]=hou[i+1]+q[i];
	int res=0;
	_rep(i,1,n)
	{
		res+=(q[i]*(hou[i+1]%P)%P);
		res%=P;
	}
//	cout<<"res="<<res<<" "<<n<<endl;
	
	cout<<(res*qmi((n*(n-1)/2)%P,P-2)%P)<<'\n';
	return ;
}
signed main()
{
	IOS;
	int T=1;
	cin>>T;
	while(T--)
		solve();
	return 0;
}
相关推荐
肥猪猪爸2 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
readmancynn2 小时前
二分基本实现
数据结构·算法
萝卜兽编程2 小时前
优先级队列
c++·算法
盼海2 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步3 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
Rstln3 小时前
【DP】个人练习-Leetcode-2019. The Score of Students Solving Math Expression
算法·leetcode·职场和发展
芜湖_4 小时前
【山大909算法题】2014-T1
算法·c·单链表
珹洺4 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
几窗花鸢4 小时前
力扣面试经典 150(下)
数据结构·c++·算法·leetcode
.Cnn4 小时前
用邻接矩阵实现图的深度优先遍历
c语言·数据结构·算法·深度优先·图论