2021年牛客暑期多校训练营4

2021年牛客暑期多校训练营4

A Course(待)

题意:

题解:

注意:

代码:

B Sample Game(待)

题意:

题解:

注意:

代码:

C LCS

题意:

给定数字a,b,c,n现在让你找到三个字符串s1,s2,s3 其中LCS(s1,s2)长度为a LCS(s2,s3)长度为b LCS(s1,s3)长度为c。而且s1,s2,s3长度都为n,如果不存在输出0,否则输出任意的一组s1,s2,s3即可

题解:

详情参考 注意LCS的含义,最长公共子序列是可以不连续的。理解含义之后就发现这居然是道签到题,构造即可。

因为a,b,c之间容斥的关系 a+b+c-2*min<=n恒成立,如果出现>的情况则直接输出NO即可,之后再进行构造。比如说:

  1. s1,s2,s3共有的用字符 a
  2. s1,s2,共有,s3没有的 b
  3. s2,s3共有,s1没有的 c
  4. s1,s3共有,s2没有的 d
  5. s1独有的 e
  6. s2独有的 f
  7. s3独有的 g

IMG_0199

注意:

注意一下格式就好了

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+5;
char s1[maxn],s2[maxn],s3[maxn];
int main()
{
    int a,b,c,n;
    scanf("%d%d%d%d",&a,&b,&c,&n);
    int mini=min(a,b);mini=min(mini,c);//得到这三个串共有的字符个数
    if(a+b+c-2*mini>n){//a-min=>s1和s2共有的但是s3没有的,b-min=>s2和s3共有的但是s1没有的,c-min=>s1和s3共有的但是s2没有的;
        printf("NO");
        return 0;
    }
    for(int i=0;i<mini;i++){
        s1[i]=s2[i]=s3[i]='a';
    }
    for(int i=mini;i<a;i++){
        s1[i]='b';
        s2[i]='b';
    }
    b-=mini;c-=mini;
    for(int i=a;i<a+b;i++){//b-mini表示的是s2和s3共有的
        s2[i]='c';
        s3[i]='c';
    }
    for(int i=a+b;i<a+b+c;i++){//c-mini表示的是s1,s3共有的
        s1[i]='d';
        s3[i]='d';
    }
    for(int i=0;i<n;i++){//自己独有的补齐即可
        if(s1[i])cout<<s1[i];
        else cout<<'e';
    }
    cout<<endl;
    for(int i=0;i<n;i++){//自己独有的补齐即可
        if(s2[i])cout<<s2[i];
        else cout<<'f';
    }
    cout<<endl;
    for(int i=0;i<n;i++){//自己独有的补齐即可
        if(s3[i])cout<<s3[i];
        else cout<<'g';
    }
    return 0;
}

D Rebuild Tree(待)

题意:

题解:

注意:

代码:

E Tree Xor(待)

题意:

现有一个无向图,两个点i,j之间的权值是w[i]^w[j],已知每一个w[i]所在的区间,现在问一共有多少种w数组,符合条件

题解:

详情参考

注意:

代码:

F Just a joke

题意:

给定一个无向图,Alice和Bob轮流进行操作,两种操作:1.删除一个点,2.删除一个联通组件,谁不能进行操作谁就输了。

题解:

操作1.删去一条边 ,边数-1。操作 2.删去没有环的联通组件 (1-2 ,1-3)边数-k点数-(k+1)

也就是说每次的操作都是边数+点数-奇数,这样一来就只和n+m有关了

注意:

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)scanf("%d%d",&x,&y);
    if((n+m)&1)printf("Alice");
    else printf("Bob");
    return 0;
}

G Product(待)

题意:

题解:

注意:

代码:

H Convolution(待)

题意:

题解:

注意:

代码:

I Inverse Pair

题意:

对给定的n个数,只能给某些数+1,或者不变,从而使得整个序列的逆序对数最少

题解:

就直接逆序对,然后输入的时候处理一下数据,我当时构造的时候也这么想过,但是我老往函数里边构造,结果就出不来🍃

注意:

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
typedef long long ll;
int a[maxn],temp[maxn];bool vis[maxn];
ll ans=0;
void merge(int x[],int l,int mid,int r)
{
    int i=l,j=mid+1;
    int k=1;
    while(i<=mid&&j<=r)
    {
        if(a[i]<=a[j])temp[k++]=x[i++];
        else temp[k++]=x[j++],ans+=mid-i+1;//ans表示的是逆序对的数目
    }
    while(i<=mid)temp[k++]=x[i++];
    while(j<=r)temp[k++]=x[j++];
    for(int i=r;i>=l;i--)
    {
        x[i]=temp[--k];
    }
}
void merge_sort(int x[],int l,int r)
{
    if(l<r)
    {
        int mid=l+r>>1;
        merge_sort(x,l,mid);
        merge_sort(x,mid+1,r);
        merge(x,l,mid,r);
    }
}
 int main()
 {
     int n;
     scanf("%d",&n);
     memset(vis,false,sizeof(vis));
     for(int i=1;i<=n;i++){
         scanf("%d",&a[i]);
         if(vis[a[i]+1])a[i]++;//a[i]这个数处于a[i]+1这个数后面,这就形成了逆序队
         vis[a[i]]=true;
     }
     merge_sort(a,1,n);
     printf("%lld",ans);
     return 0;
 }

J Average

题意:

给定一个b,c数组,有一个矩阵w,w[i] [j]=b[i]+c[j],问长≥x,宽≥y的子矩阵所有元素最大平均值为多少

题解:

将二维放缩至一维上去写,问题转化成求b区间长度大于等于x的最大平均值和c区间长度大于等于y的最大平均值.通过一个二分来求平均值,用前缀和来维护

注意:

注意二分的时候r-l>1e-10

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
double a[maxn],b[maxn],sum[maxn];
double solve(int n,int m)//m表示的是长度
{
    for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
    double l=1e-5,r=1e5;
    while(r-l>1e-10){
        double mid=(l+r)/2;
        for(int i=1;i<=n;i++)b[i]=a[i]-mid;
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+b[i];
        double mini=1e6,maxm=-1e6;
        for(int i=m;i<=n;i++){
            mini=min(mini,sum[i-m]);//注意他们之间的长度只会更长
            maxm=max(maxm,sum[i]-mini);//得到的就是区间和
        }
        if(maxm>=0) l=mid;//可行,值可能更大
        else r=mid;
    }
    return r;
}
int main()
{
    int n,m,x,y;
    scanf("%d%d%d%d",&n,&m,&x,&y);
    printf("%.10lf",solve(n,x)+solve(m,y));
    return 0;
}
posted @   Aaryn21  阅读(62)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示