每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

牛客练习赛109(C,D)

牛客练习赛109(C,D)

C

C

这个题大意是给你一个dfs序,和每一个点的size,我们需要的答案是这些点的所有边,但是我们还要注意这些边的输出也是有要求的,比如一个边(u,v)必须是v>u,然后这些边是第几个输入的是按照第一个点的大小使得这些u以单调不减的方式来排序(这个排序我赛时一直没搞明白,真坑,输出就输出,还排什么序呢)

看到这个我第一反应是用dfs

因为我们都知道dfs序列好像都是从根节点出发的,那么我们就可以知道出发点了,然后从这个点u开始遍历,然后对于这个点后面的siz[u]1个节点进行遍历,那么对于在这个过程之间相邻的两个点一定是相连的

然后就可以写代码了

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int siz[maxn],dfn[maxn];
int n;
vector<int>g[maxn];
vector<pair<int,int>>ans;
int pos;
int p=0;
bool cmp(pair<int,int> x,pair<int,int> y)
{
    if (x.first!=y.first)
    {
        return x.first<y.first;
    }
    return x.second<y.second;
}
void dfs(int u,int cnt)
{
    while (pos<n&&cnt!=siz[u])
    {
        pos++;
        int v=dfn[pos];
       ans.push_back({min(u,v),max(u,v)});
      //  cout<<min(u,v)<<" "<<max(u,v)<<'\n';//这个好像不好处理那个输出的排序,后面我用了pair才过了的
        cnt+=siz[v];
        if (siz[v]==1) continue;
        dfs(v,1);
    }
    return ;
}
int main ()
{
    ios_base::sync_with_stdio(false);//赛时没加超时了
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin>>n;
   int root=0;
    for (int i=1;i<=n;i++)
    {
       cin>>dfn[i];
    }
    for (int i=1;i<=n;i++)
    {
        cin>>siz[i];
    }
    pos=1;
    dfs(dfn[1],1);
    sort(ans.begin(),ans.end(),cmp);
    for (auto [x,y]:ans)
    {
        cout<<x<<" "<<y<<'\n';
    }
    return 0;
}

D

D

题目大意就是给你n个数,还有m,你可以进行k次操作,每进行一次操作,都会选择一个ij,让ai变成ai+m,aj变成ajm,而且i可以等于j,那么就意味着我们可以进行小于等于k次有效操作,让这n个数的累乘最大

高中的时候我们学过基本不等式

a×b<=(a+b2)2

我们两个两个来看,这两个数的和是固定的,我们要想这两个数的和最大,就只能让上面这个不等式成立,而只有a==b才可以让等于号成立,所以我们可以知道要让和固定两个数的乘积尽量大,只有这两个数的差值尽量小

然后要让这k个操作发挥到最好的效果,最好是让这些数的两个极端来进行这个操作,那么这n个数整体也相对于平均了

对于快速求得最大最小值,并且还可能存在相同的数值,我觉得可以用multise

还有如果只有1个数的话,不管操作多少次,答案都还是那个值,可以直接输出了

#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int mod=1e9+7;
int n,m,k;
multiset<int>ans;
signed main ()
{
    cin>>n>>m>>k;
    for (int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        ans.insert(x);
    }
    while (k--&&n>1)
    {
        auto x=ans.begin();
        auto y=ans.end();
        y--;
        int t=*x;
        int tt=*y;
        int a=t+m;
        int b=tt-m;
        if (tt-t<m) break;//使两个数之间的差值变小,只有这两个数原来的差值大于m
        //如 m=5  5和9可以变成10 4差值变成6了,那么就会使答案变小,
        //如 5  11 可以变成10 6 差值有原来的6变成4,可以是答案变小
        //为什么这些数差值更小累乘就更小
        //可以想想基本不等式
        ans.erase(x);
        ans.erase(y);
        ans.insert(a);
        ans.insert(b);
    }
  
    int sum=1;
    for (auto x:ans)
    {
        sum=(sum*x)%mod;
    }
    cout<<sum<<'\n';
    return 0;
}
posted @   righting  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示