牛客练习赛109(C,D)
牛客练习赛109(C,D)
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
题目大意就是给你\(n\)个数,还有\(m\),你可以进行\(k\)次操作,每进行一次操作,都会选择一个\(i\)和\(j\),让\(a_i\)变成\(a_i+m\),\(a_j\)变成\(a_j-m\),而且\(i\)可以等于\(j\),那么就意味着我们可以进行小于等于\(k\)次有效操作,让这\(n\)个数的累乘最大
高中的时候我们学过基本不等式
\[a\times b<=(\frac{a+b}{2})^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;
}

浙公网安备 33010602011771号