3.17~3.23

牛客周赛 85

A

签到

#include <bits/stdc++.h>
using namespace std;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
	cin >> n;
	cout << (n%2 ? "kou\n" : "yukari\n");
	return 0;
}

B

贪心

由题目可知,小红和小紫的拿取元素的倾向都是拿尽可能小的元素

因此直接对数组升序排序,然后遍历数组对x进行操作即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+1;

int arr[maxn];

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
	cin >> n;
	for(int i=0;i<n;i++)
		cin >> arr[i];
	int x = 0;
	sort(arr,arr+n);
	for(int i=0;i<n;i++){
		if(i % 2) x -= arr[i];
		else x += arr[i];
	}
	cout << x << '\n';
	return 0;
}

C

相邻两个元素不同的情况叫听“突起”

这题有两种突起:10,01

显然,这两种突起最多各只能出现两次,否则就无法挽回大局

遍历数组判断即可

#include <bits/stdc++.h>
using namespace std;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t;
	cin >> t;
	while(t--){
		string s;
		cin >> s;
		int diff_01 = 0, diff_10 = 0, si = s.size(), pd = 1;
		for(int i=0;i<si-1;i++){
			if(s[i] != s[i+1]){
				if(s[i] == '1')
					diff_10++,i++;
				else diff_01++,i++;
			}
			if(max(diff_10,diff_01) > 2){
				pd = 0;
				break;
			}
		}
		cout << (pd ? "Yes\n" : "No\n");
	}
	return 0;
}

D

对0和1做一个前缀和,然后首尾双层遍历

i表示删除前i个,j表示从后往前选择的第j个

如果第j个满足双生串的条件,就停止循环,否则一直向前枚举

通过前缀和相减的方式快速算出有几个0或1

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+1;

int n;
double win = 0, defeat = 0;
string s;
int q0[maxn], q1[maxn];

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> s;
	if(n==1){
		cout << "0\n";
		return 0;
	}
	if(s[0] == '0')
		q0[0] = 1, q1[0] = 0;
	else q0[0] = 0, q1[0] = 1;
	for(int i=1;i<n;i++){
		q0[i] = q0[i-1] + (s[i] == '0');
		q1[i] = q1[i-1] + (s[i] == '1');
	}
	for(int i=0;i<n;i++){
		int pd=1;
		for(int j=n-1;j>i;j--){
			int n0 = q0[j] - q0[i], n1 = q1[j] - q1[i];
			if(!(n0 % 2) && !(n1 % 2) && max(n0,n1)){
				win++;
				pd = 0;
				break;
			}
		}
		if(pd) defeat++;
	}
	cout << win/(win + defeat) << '\n';
	return 0;
}

程协杯&19

B

观察发现,a为偶数甲胜,a为奇数乙胜

#include <bits/stdc++.h>
using namespace std;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
    cin >> n;
    while(n--){
        int a;
        cin >> a;
        if(a%2 == 0){
            cout << "jia wins\n";
        }
        else cout <<"yi wins\n";
    }
	return 0;
}

E

考虑上一排怎么到下一排去,假设下一排的无车区间是[L,R],那么能成功从上一排到下一排的位置是[L-K,R+K]

因此从头开始遍历数组,逐排判断即可

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+1;
int L[N],R[N];

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
    int n,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++)
        cin >> L[i] >> R[i];
    if(n == 1){
        cout << "Phoenix\n";
        return 0;
    }
    int old_l,old_r;
    int minn = 0, maxn = 1e6;
    old_l = max(minn,L[2]-k);
    old_r = min(maxn,R[2]+k);
    int pd = 1,times;
    for(int i=1;i<=n;i++){
        old_l = max(old_l,L[i]);
        old_r = min(old_r,R[i]);
        if(old_l > old_r){
            pd = 0;
            times = max(2,i);
            //cout << L[i] <<' ' << R[i] << '\n';
            break;
        }
        old_l = max(minn,old_l-k);
        old_r = min(maxn,old_r+k);
    }
    if(pd) cout << "Phoenix\n";
    else cout << times << '\n';
	return 0;
}

G

Set搞定

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+1;

set <int> s;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
    cin >> n;
    for(int i=0;i<n;i++){
        int cache;
        cin >> cache;
        s.insert(cache);
    }
    cout << s.size() << '\n';  
	return 0;
}

J

观察发现,牌的大小从1到nm里,不属于甲的n张牌里的数就是会对甲造成威胁的,假的牌就是"My",不属于甲的牌的数就是"Kong",从1到nm里,遇到一个"My"就My++,遇到一个"Kong"就My--(但是My要大于等于0)

输出My即可

#include <bits/stdc++.h>
using namespace std;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int m,n;
    cin >> m >> n;
    int a[51];
    for(int i=0;i<n;i++)
        cin >> a[i];
    sort(a,a+n);
    int maxn = n*m , index = 0;
    int my=0,kong=0,wins=0;
    for(int i=1;i<=maxn;i++){
        if(i == a[index]){
            wins++;
            index++;
        }
        else{
            wins = max(0,wins-1);
        }
        //cout << wins << '\n';
    }
    //cout << my << ' '<< kong << '\n';
    cout << wins << '\n';
	return 0;
}

K

好坑的一道题,我用正常方法怎样都会超时......后来用二分优化,还是Wa,自己造数据debug才发现爆longlong了,于是就出现了if elseif elseif...这一幕

但题还是不难的

#include <bits/stdc++.h>
#define int long long
using namespace std;

signed main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int n,m;
        cin >> n >> m;
        if(m==1){
			cout << "1\n";
			continue;
		}
		if(n < m){
			cout << "1\n";
			continue;
		}
        int m_ = 0,m_old=m_;
        int mid, l=0, r;
        if(m==2) r=33;
        else if(m==3) r=20;
        else if(m==4) r=16;
        else if(m==5) r=14;
        else if(m==6) r=12;
        else if(m==7) r=11;
        else if(m==8) r=10;
        else if(m==9) r=10;
        else if(m<=11) r=9;
        else r=8;
        while(l < r){
            mid = (l+r) >> 1;
            m_ = pow(m,mid);
            if(m_ < n)
                l = mid+1;
            else r = mid;
            //cout<<"l:"<<l<<" r:"<<r<<" mid:"<<mid<<" m_:"<<m_<<'\n'; 
        }
        if(m_>n){
        	m_old = m_/m;
        	if(m_-n >= n-m_old) mid--;
		}
		if(m_<n){
			m_old = m_*m;
			if(m_old-n < n-m_) mid++;
		} 
        cout << max(1LL,mid) << '\n';

    }
    return 0;
}

D

居然BFS搜就行了....

可以知道,走一次k就行,再用一次瞬移就跟没用差不多

遇到k大于0的情况就判断从结束点对面直接到结束点和正常走哪个小

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf = 1e8;
const int maxn = 2e5+5;

int n,k,a,b,x,y,ans=0;
int vis[maxn]={0},step[maxn];

void bfs(){
	queue <pair<int,int>> q;
	q.push({a,0});
	while(!q.empty()){
		pair<int,int> node = q.front();
		q.pop();
		if(vis[node.first]) continue;
		vis[node.first]++;
		step[node.first] = node.second;
		q.push({(node.first+x)%n, node.second+1});
		q.push({(node.first-y+n)%n, node.second+1});
	}
}

signed main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> k >> a >> b >> x >> y;
    a--,b--;
	memset(step,inf,sizeof(step)); 
	bfs();
	ans = step[b]; 
	if(k > 0)
		ans = min(step[b],step[(b+n/2)%n]+1);
	cout << (ans>=inf ? -1 : ans) << '\n';
	return 0;
}

I

01背包基础上改的

对于题目玩的花样,我们就做两次dp,一次从前往后做,一次从后往前做,求出,每个点的最优解

01背包的状态转移方程为

dp1[i][j] = max(dp1[i-1][j],dp1[i-1][j-c[i]]+w[i]);(前->后)

dp2[i][j] = max(dp2[i+1][j],dp2[i+1][j-c[i]]+w[i]);(后->前)

然后再遍历一遍n,找到最大的

dp1[i-1][m]+dp2[i+1][m]+w[i]

输出即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+2;

int dp1[maxn][maxn], dp2[maxn][maxn], c[maxn], w[maxn];
int n,m;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	memset(dp1,0,sizeof(dp1));
	memset(dp2,0,sizeof(dp2));
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		int wi,vi;
		cin >> wi >> vi;
		c[i] = wi;
		w[i] = vi;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(j >= c[i])
				dp1[i][j] = max(dp1[i-1][j],dp1[i-1][j-c[i]]+w[i]);
			else dp1[i][j] = max(dp1[i][j],dp1[i-1][j]);	
		}
	for(int i=n;i>=1;i--)
		for(int j=1;j<=m;j++){
			if(j >= c[i])
				dp2[i][j] = max(dp2[i+1][j],dp2[i+1][j-c[i]]+w[i]);
			else dp2[i][j] = max(dp2[i][j],dp2[i+1][j]);	
		}
	int ans = 0;
	for(int i=1;i<=n;i++){
		ans = max(ans,dp1[i-1][m]+dp2[i+1][m]+w[i]);
	}
	cout << ans << '\n';
	return 0;
}

LG P1135

无意间找到了一题,和程协杯的D真的好像......

都是bfs暴搜

#include <bits/stdc++.h>
using namespace std;
const int inf = 1e6;

int n,a,b;
int step[201],vis[201]={0},room[201]={0};

void bfs(){
	queue <pair<int,int>> q;
	q.push({a,0});
	while(!q.empty()){
		pair<int,int> node = q.front();
		q.pop();
		if(vis[node.first]) continue;
		vis[node.first] = 1;
		room[node.first] = node.second;
		if(node.first+step[node.first] <= n) 
			q.push({node.first+step[node.first],node.second+1});
		if(node.first-step[node.first] >= 1) 
			q.push({node.first-step[node.first],node.second+1});
	}
}

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> a >> b;
	for(int i=1;i<=n;i++)
		cin >> step[i];
	if(a == b){
		cout << "0\n";
		return 0;
	} 
	bfs();
	if(room[b] == 0) room[b] = -1;
	cout << room[b] << '\n';
	return 0;
}
posted @ 2025-06-14 12:25  HLAIA  阅读(4)  评论(0)    收藏  举报