Codeforces Round 938 (Div. 3)

A. Yogurt Sale

#include
#define endl '\n'
#define int long long
using namespace std;
int n,a,b;
void solve() {
	cin>>n>>a>>b;
	if(2*a<=b) cout<<n*a<<endl;
	else{
		int ans=n/2*b;
		if(n%2) ans+=a;
		cout<<ans<<endl;
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Progressive Square

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=510;
int a[N*N];
int n;
int c,d;
void solve() {
	cin>>n;
	cin>>c>>d;
	for(int i=1;i<=n*n;i++) cin>>a[i];
	sort(a+1,a+1+n*n);
	vector<int>ans;
	int t=a[1];
	for(int i=0;i<n;i++){
		ans.push_back(t);
		t+=d;
	}
	vector<int>res;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res.push_back(ans[i]+c*j);
		}
	}
	sort(res.begin(),res.end());
	for(int i=0;i<n*n;i++){
		if(a[i+1]!=res[i]){
			cout<<"NO"<<endl;
			return;
		}
	}
	cout<<"YES"<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C. Inhabitant of the Deep Sea

按照题意模拟即可

对头和尾进行操作,取头和尾小的那个,记为t,然后头减去t,尾减去t,相当于头减1,尾减1,这样的操作做了t次,然后将变为0的删掉(k需要大于等于2 * t)

特殊情况,如果头为小的那个,即为t,然后尾大于t,那么可以判断一下,如果k等于2 * t -1,那么可以删掉头,但是不能对尾进行操作了

最后可能剩下一个元素,看剩余的操作次数能否将它删掉

#include
#define endl '\n'
#define int long long
using namespace std;
int n,k;
void solve() {
	cin>>n>>k;
	deque<int>q;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		q.push_back(x);
	}
	int ans=0;
	while(q.size()>1){
		int t=min(q.front(),q.back());
		if(k>=2*t){
			k-=2*t;
			q.front()-=t;
			q.back()-=t;
			if(q.front()==0) q.pop_front(),ans++;
			if(q.back()==0) q.pop_back(),ans++;
		}
		else if(k==2*t-1&&q.front()==t){
			ans++;
			cout<<ans<<endl;
			return;
		}
		else break;
	}
	if(q.size()==1){
		if(k>=q[0]) ans++;
	}
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

D. Inaccurate Subsequence Search

滑动窗口,维护双端队列内的元素个数为m,将枚举到的元素放入队尾,将队头弹出,并实时维护匹配个数,如果匹配个数大于等于k,则ans++

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int a[N],b[N];
int n,m,k;
void solve() {
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	map<int,int>target;
	for(int i=1;i<=m;i++) cin>>b[i],target[b[i]]++;
	int match=0;
	int ans=0;
	deque<int>q;
	map<int,int>mp;
	for(int i=1;i<=m;i++){
		q.push_back(a[i]);
		if(mp[a[i]]<target[a[i]]){
			if(target[a[i]]){
				match++;
			}
		}
		mp[a[i]]++;
	}
	if(match>=k) ans++;
//	for(auto v:q) cout<
//	cout<
//	cout<
//	cout<<"========="<
	for(int i=m+1;i<=n;i++){
		if(mp[q.front()]<=target[q.front()]){
			if(target[q.front()]) match--;
		} 
		mp[q.front()]--;
		q.pop_front();
		q.push_back(a[i]);
		if(mp[a[i]]<target[a[i]]){
			if(target[a[i]]) match++;
		}
		mp[a[i]]++;
		if(match>=k) ans++;
//		for(auto v:q) cout<
//		cout<
//		cout<
//		cout<<"========="<
	}
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

E. Long Inversions

首先对连续一段区间进行操作01反转(相当于和1异或),要保证将所有元素都变为1,那么常用的方法就是从头到尾如果为0的话就进行操作,将其一个一个变为为1,这样能保证全变为1,而且如果为0的话,操作区间是必须要包含到的,不然的话就不能将那个0变为1

枚举所有的k进行模拟即可,check k是否合法

对区间进行异或操作,可以用差分,差分数组d,比如对[l,r]和1异或,那么d[l] ^ =1,d[r+1] ^ =1

由于我们是从前往后一个一个枚举的,我们需要看后面的元素在进行操作之后是0还是1,那么需要对差分数组进行前缀和操作,得到每个位置具体进行的是什么操作,一边枚举一边对差分数组进行前缀和操作即可,因为前面不会再被操作了

如果进行的区间超出边界了,那么说明k不合法

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=5010;
int n;
int a[N];
int d[N];//差分数组
string s;
bool check(int k){
	for(int i=1;i<=n;i++) d[i]=0;
	bool ok=true;
	for(int i=1;i<=n;i++){
		d[i]^=d[i-1];
		if((a[i]^d[i])==0){
			if(i+k-1>n) return false;
			d[i]^=1;
			d[i+k]^=1;
		}
	}
	return true;
}
void solve() {
	cin>>n;
	cin>>s;
	s=' '+s;
	for(int i=1;i<=n;i++) a[i]=s[i]-'0';
	for(int k=n;k>=1;k--){
		if(check(k)){
			cout<<k<<endl;
			return;
		}
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

F. Unfair Game

当所有元素异或和为0时,Bob赢

首先,1 ^ 2 ^ 3 = 0

4的个数必须为偶数,异或和才能为0,所以如果4的个数为奇数的话,那么先删掉一个4

然后如果1,2,3的个数均为奇数的话,那么可以作为一次贡献

其它的话,就是每个数两两异或和为0作为一次贡献

比如1的个数为3,2的个数为5,3的个数为7,4的个数为4

那么一开始的序列异或为即为0,贡献在于1个3,一个5,一个7,然后将这三个数删掉,则为2个1,4个2,6个3,4个4

然后删掉2个1,序列异或和仍为0,则2个1提供了一次贡献,同理,删掉2个2,提供一次贡献,再删掉2个2,提供一次贡献,以此类推

贡献总数即为a[1]/2+a[2]/2+a[3]/2+a[4]/2,如果a[1],a[2],a[3]均为奇数则再多一次贡献

#include
#define endl '\n'
#define int long long
using namespace std;
int a[5];
void solve() {
	for(int i=1;i<=4;i++) cin>>a[i];
	int ans=0;
	for(int i=1;i<=4;i++){
		ans+=a[i]/2;
	}
	if(a[1]%2&&a[2]%2&&a[3]%2) ans++;
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,c++,数据结构)