2021暑期牛客多校4

本文探讨了通过暴力搜索和巧妙设计的算法解决两道典型问题:字符串公共字符长度和博弈策略。暴力法用于计算字符串公共部分,而动态规划和奇偶性判断应用于博弈问题。展示了如何在有限时间内找到最佳解并优化逆序对和平均数计算。
摘要由CSDN通过智能技术生成

C. LCS
构造,我是暴力的…
题目:s1, s2, s3, 公共的字符长度是a,b,c。
思路:暴力…
代码:

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

struct vv{
    int u, id;
    string s;
};

bool cmp1(vv a, vv b){
    return a.u < b.u; 
}

bool cmp2(vv a, vv b){
    return a.id < b.id;
}
//暴力出奇迹,哈哈哈
int main(){
    int a, b, c;
   vector<vv> t(3);
    for(int i = 0; i < 3; i++){
        cin >> t[i].u;
        t[i].id = i;
        if(i == 0){
            a = t[i].u;
        }else if(i == 1){
            b = t[i].u;
        }else {
            c = t[i].u;
        }
    }
    int n;
    cin >> n;
    sort(t.begin(), t.end(), cmp1);
    if(n - t[1].u + t[0].u < t[2].u ){
        cout << "NO\n";
        return 0;
    }
    char str = 'a';
    for(int i = 1; i <= t[0].u; i++){
        (t[0].s).push_back(str);
        (t[1].s).push_back(str);
    }
    for(int i = 1; i <= n-t[0].u; i++){
        (t[0].s).push_back(str+1);
        (t[1].s).push_back(str+2);
    }
    int cot = 0;
    for(int i = 1; i <= n; i++){
        if(i >= 1 && i <= t[1].u){
            (t[2].s).push_back((t[1].s)[i-1]);
            continue;
        }
        if(cot < (t[2].u - t[0].u)) {(t[2].s).push_back((t[0].s)[i-1]); cot++;}
        else{
            t[2].s.push_back('z');
        }
    }
    sort(t.begin(), t.end(), cmp2);
    int cot1 = 0, cot2 = 0;
    for(int i = 0; i < n; i++){
        if((t[0].s)[i] == (t[1].s)[i]) cot1++;
        if((t[1].s)[i] == (t[2].s)[i]) cot2++;
    }
    if(cot1 == a && cot2 == b)
    {cout << t[0].s << endl << t[1].s << endl << t[2].s << endl;}
    else if(cot1 == a && cot2 == c){
        cout << t[1].s << endl << t[0].s << endl << t[2].s << endl;
    }else if(cot1 == b && cot2 == a){
        cout << t[2].s << endl << t[1].s << endl << t[0].s << endl;
    }else if(cot1 == b && cot2 == c){
        cout << t[2].s << endl << t[0].s << endl << t[1].s << endl;
    }else if(cot1 == c && cot2 == a){
        cout << t[2].s << endl << t[0].s << endl << t[1].s << endl;
    }else if(cot1 == c && cot2 == b){
        cout << t[0].s << endl << t[2].s << endl << t[1].s << endl;
    }
}

F. just a joke
思维题。
题目大意:
可以删边或者删无环的联通分量。 然后谁先删玩谁赢。
思路:
删边掉一条边,0个点。删分量掉k个点,k-1边。
所以每次操作过奇偶性不变。依次,判断奇偶即可。
代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n, m;
    cin >> n >> m;
    if((n+m) & 1) cout << "Alice\n";
    else cout << "Bob\n";
}

I. Inverse Pair
简单思维题。
题目:
对某个数进行1次或0次加1操作。求逆序对数量最少。
思路:
对某个数加1只能改变比他大1的数的一个逆序对。
因此我们先求出所有的逆序对,然后结构体排序,从后往前找,比较下标位置。(从前往后没试过)。
代码:

#include <cstdio>
#include <iostream>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

const int maxn=2e5+5;

struct vv{
    int v, id;
};

bool cmp(vv c, vv d){
	return c.v < d.v;
}

int n;
vv a[maxn],b[maxn];
vv f[maxn];
LL ms(int l,int r){
    if(l>=r) return 0;
    int m=(l+r)>>1;
    LL t1=ms(l,m),t2=ms(m+1,r);
    LL t3=0;
    int i=l,j=m+1,p=l;
    while(i<=m&&j<=r){
        if(a[i].v>a[j].v){
            b[p++].v=a[j++].v;
            t3+=m-i+1;
        }
        else b[p++].v=a[i++].v;
    }
    
    while(i<=m) b[p++].v=a[i++].v;
    while(j<=r) b[p++].v=a[j++].v;
    for(int i=l;i<=r;i++) a[i].v=b[i].v;
    return t1+t2+t3;
}
int main(){
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n;
    for(int i=1;i<=n;i++) {
    	cin >> a[i].v;
    	f[i].v = a[i].v;
    	f[i].id = i;
	}
	 
    LL ans = ms(1,n);
    sort(f+1, f+1+n, cmp);
    
//    for(int i = 1; i <= n; i++){
//    	cout << f[i].v << " " << f[i].id << endl;
//	}
    for(int i = n; i >= 1; i--){
    	if(f[i-1].id > f[i].id) 
    	{
    		ans--;
    		i--;
		}
	}
	cout << ans << endl;
    return 0;
}

J. Average
二分答案。
题目大意:
数组a表示i, 数组b表示j, 矩阵G[i][j] = a[i] + b[j]。
现在给出一个框的最小范围,求框中的值相加然后除以面积最大是多少。
思路:
把上面的描述化简,发现就是一段连续区间相加除以长度,求最大。
然后就变成了板子题…
洛谷搜平均数。
代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int inf = 0x3f3f3f3f;
#define eps 0.0000000001
vector<int> a(N), b(N);
vector<double> sum(N);

bool check(vector<int> f, double mid, int n, int m){
    double MIN = 0;
    double MAX = -1*inf;
    for(int i = 1; i <= n; i++){
        sum[i] = sum[i-1] + f[i] - mid;
        if(i >= m){
            MIN = min(MIN, sum[i-m]);
            MAX = max(MAX, sum[i]-MIN);
        }
    }
    return MAX >= 0;
}

double solve(vector<int> f, int n, int m){
    double l = 0, r = 1e7;
    while(r-l > eps){
        double mid = (l+r)/2;
        if(check(f,mid,n,m)) l = mid;
        else r = mid;
    }
    return l;
}


int main(){
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n1, n2, m1, m2;
    cin >> n1 >> n2 >> m1 >> m2;
    for(int i = 1; i <= n1; i ++) cin >> a[i];
    for(int i = 1; i <= n2; i ++) cin >> b[i];
    
    double ans1 = solve(a, n1, m1);
    double ans2 = solve(b, n2, m2);
//     cout << fixed << setprecision(10) << "ans1 = " << ans1 << " ans2 = " << ans2 << endl;
    cout << fixed << setprecision(10) << (ans1 + ans2) << endl;
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值