Educational codeforces round 112 (rated for Div. 2)

Posted by jola on Thu, 16 Sep 2021 02:35:10 +0200

A. PizzaForces

A. PizzaForces
Easy to understand, omitted
Idea: simply be greedy. Divide n into such forms as n=10+x+10y, then 10y individuals use y large cakes, and the remaining 10+x uses three combinations of cakes to see which saves the most time

AC_code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
	int t;
	cin>>t;
	while(t--){
		ll n;
		cin>>n;
		ll temp = n%10;
		ll ans = n/10;
		ll sum = 0;
		if(ans==0){
			if(temp<=6)
			sum+=15;
			else if(temp<=8){
				sum+=20;
			}
			else sum+=25;
		}
		else{
		if((temp==0||temp==2||temp==4||temp==6||temp==8)){
			sum = n*2.5;
		}
		else{
			sum = (ans-1)*25;
			if(temp==1) sum+=30;
			else if(temp==3) sum+=35;
			else if(temp==5) sum+=40;
			else if(temp==7) sum+=45;
			else if(temp==9) sum+=50;
		}
	    } 
	    cout<<sum<<'\n';
	}
	return 0;
}

C. Coin Rows

C. Coin Rows
Main idea of the topic: now there are 2*n grids, and each grid has a weight. Now Alice and Bob are at the point of (1,1), which stipulates that they can only go down or right. Alice first goes from (1,1) to (2,n), and Alice will change the weight value of the grid (including the starting point) to 0, and then bob goes from (1,1) to (2,n). Now Alice wants Bob to minimize the sum of path weights, Bob wants to maximize the sum of the weights of the paths he passes through. Both of them adopt the optimal strategy. What is the sum of the weights of Bob in the end?

Idea: obviously, it's not difficult for us to find that when Alice leaves, Bob has and only two walking methods that can maximize the sum of path weights, namely 7-shape and L-shape walking methods, so we only need to consider how Alice walks to minimize the sum of Bob's path weights, and use prefix and to deal with the sum of path weights

AC_code:

#include<bits/stdc++.h>
using namespace std;
const int Maxn = 1e5+10;
int sum1[Maxn]={0};
int sum2[Maxn]={0};
int main(){
	int t;
	cin>>t;
	while(t--){
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			int di;
			cin>>di;
			sum1[i] = sum1[i-1]+di;
		}
		for(int i=1;i<=n;i++){
			int di;
			cin>>di;
			sum2[i] = sum2[i-1]+di;
		}
		int ans = 1e9+10;
		for(int i=1;i<=n;i++){
			ans = min(ans,max(sum1[n]-sum1[i],sum2[i-1]));
		}
		cout<<ans<<'\n';
	}
	return 0;
}

D. Say No to Palindromes

D. Say No to Palindromes
Question meaning: give you a string that only consists of abc. Now you can modify the character at any position of the string to a or b or c. ask how many times you need to modify it at least so that all substrings with a length greater than 1 are not palindromes

Idea: the string is only composed of three characters abc, so any three adjacent strings cannot be repeated. For example, abc ABC. Then we can find that the string meeting the requirements has a circular section with a length of 3. Therefore, there are six types of circular sections, namely abc, acb, bac, bca, cab and cba, Therefore, we only need to modify the original string into these six circular section strings, and then take the minimum number of modifications. So we set d p [ i ] [ j ] dp[i][j] dp[i][j] indicates the number of times to modify the first j characters into the i-th circular section. For the query of [L,R], 1 < = I < = 6, min (DP [i] [R] - DP [i] [L-1]) is the answer

AC_code:

#include<bits/stdc++.h>
using namespace std;
const int Maxn = 2e5+10;
string s[6] = {"abc","bac","acb","bca","cab","cba"};
string str;
int n,m;
int f[6][Maxn]={0};//dp[i][j] indicates how many characters need to be modified from the first I characters to the ith palindrome string 
void solve(){
	for(int i=0;i<6;i++){
		for(int j=1;j<=n;j++){
			f[i][j] = f[i][j-1]+(s[i][(j-1)%3]!=str[j-1]);
		}
	}
	return ;
}
int main(){
	cin>>n>>m;
	cin>>str;
	solve();
	while(m--){
		int l,r;
		cin>>l>>r;
		int res = Maxn;
		for(int i=0;i<6;i++){
			res = min(res,f[i][r]-f[i][l-1]);
		}
		cout<<res<<'\n';
	}
	return 0;
}

E. Boring Segments

E. Boring Segments
Main idea of the title: omitted
Idea: this question is not about interval coverage, but connectivity,
For example, [1,3] and [4,5] are not connected because there is no intersection between segments
And [1,3] and [3,5] are connected
The processing method is to set m –, the right endpoint of each line segment, r –,
In this way, there is no need to judge the intersection, just judge whether it covers [1,m]
In the classical interval connectivity operation, all given intervals and the right endpoint of the queried interval can be - 1, and then judge whether an interval is connected. Just judge whether the minimum value of the interval is 0. In this way, it can be solved by maintaining the minimum value of the interval with the segment tree

AC_code:

#include<bits/stdc++.h>
#define ls dep<<1
#define rs dep<<1|1
using namespace std;
const int Maxn = 3e5+10;
const int Maxm = 1e6+10;
int n,m;
typedef struct node{
	int l,r,val;
}Node;
Node stu[Maxn];
int tr[Maxm*4]={0};
int lazy[Maxm*4]={0};
void pushup(int dep){
	tr[dep] = min(tr[ls],tr[rs]);
	return ;
}
void pushdown(int dep){
	if(lazy[dep]!=0){
		lazy[ls]+=lazy[dep];
		lazy[rs]+=lazy[dep];
		tr[ls]+=lazy[dep];
		tr[rs]+=lazy[dep];
		lazy[dep] = 0;
		pushup(dep);
	}
	return ;
}
void update(int l,int r,int ql,int qr,int dep,int val){
//	cout<<l<<' '<<r<<'\n';
	if(ql<=l&&r<=qr){
		tr[dep]+=val;
		lazy[dep]+=val;
		return ;
	}
	pushdown(dep);
	int mid = l+r>>1;
	if(ql<=mid) update(l,mid,ql,qr,ls,val);
	if(qr>mid) update(mid+1,r,ql,qr,rs,val);
	pushup(dep);
	return ;
}
int query(int l,int r,int ql,int qr,int dep){
	if(ql<=l&&r<=qr){
		return tr[dep];
	}
	pushdown(dep);
	int mid = l+r>>1;
	int res = 1e6+10;
	if(ql<=mid) res = min(res,query(l,mid,ql,qr,ls));
	if(qr>mid) res = min(res,query(mid+1,r,ql,qr,rs));
	pushup(dep);
	return res;
}
int cmp(Node a,Node b){
	return a.val<b.val;
}
int solve(){
	int res = 1e6+10;
    int l=1,r=1;
    update(1,m,stu[1].l,stu[1].r,1,1);    
    while(l<=r&&r<n){
    	while(query(1,m,1,m,1)&&l<=r){
    	res = min(res,stu[r].val-stu[l].val);
        update(1,m,stu[l].l,stu[l].r,1,-1);
    	l++;
		}
		r++;
	    update(1,m,stu[r].l,stu[r].r,1,1);
	}
		while(query(1,m,1,m,1)&&l<=r){
    	res = min(res,stu[r].val-stu[l].val);
        update(1,m,stu[l].l,stu[l].r,1,-1);
    	l++;
		}
	return res;
}
int main(){
	 scanf("%d %d",&n,&m);
	 m--;
	 for(int i=1;i<=n;i++){
	    scanf("%d %d %d",&stu[i].l,&stu[i].r,&stu[i].val);
	    stu[i].r--;
	 }
	 sort(stu+1,stu+n+1,cmp);
	 printf("%d",solve());
	 return 0;
}

Topics: data structure dp CodeForces