Codeforces Round #670 (Div. 2)A-D题解
//写于rating值1987/2184
//补档

比赛链接:https://codeforces.ml/contest/1406

A题
贪心,施行

题意为给你一堆自然数,让你把他们分成两个部分。两个部分当中的各自没出现的最小的自然数相加,要求这个结果最大,询问这个最大结果是多少。

直接贪心依次取两个部分的数就可以了。
从0开始连续+1最多可以取到x,那么这个部分没出现的最小自然数就是x+1了,也是我们使用当前剩下的数字能得到的最大值。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;int num[107];//记录每个数字出现了几次int32_t main()
{IOS;int t;cin>>t;while(t--){memset(num,0,sizeof(num));int n;cin>>n;for(int i=0;i<n;i++){int x;cin>>x;num[x]++;}int ans=0;for(int j=0;j<2;j++)//执行两次,分为两个部分{for(int i=0;1;i++){if(i==101) {ans+=101;break;}//循环到101就可以结束了,输入数据最大也只有100if(num[i]==0) {ans+=i;break;}//当前数字不存在,则就为当前部分的最小未出现自然数,累加到答案并结束循环else num[i]--;//代表使用一个数字到当前部分里}}cout<<ans<<endl;}
}

B题
贪心,分类讨论,简单整体思维

题意为给定一个数列,你可以从中任意挑选5个数字乘起来(题意理解成这样就很简单了),希望你求出最大的结果。

这里任意挑选5个数字么,根据最后结果是正还是负(0可以包含在任意一种情况里),我们对最后结果的绝对值倾向是不同的。
如果结果为正,那么我们希望绝对值尽可能大。
如果结果为负,那么我们希望绝对值尽可能小。

而挑选5个数字,我们可以按照其中负数出现的次数,来决定最后结果的正负性。
由此我们可以把负数出现0,2,4次,和出现1,3,5次分为两种情况分别讨论,取各自情况的最大值即可。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;vector<ll>zhengshu,fushu;int32_t main()
{IOS;int t;cin>>t;while(t--){int n;cin>>n;for(int i=0;i<n;i++){ll x;cin>>x;if(x<0) fushu.push_back(x);else zhengshu.push_back(x);}sort(fushu.begin(),fushu.end());sort(zhengshu.begin(),zhengshu.end());ll ans=-llINF;for(ll i=1;i<=5;i+=2)//正数或者0的出现次数为奇数,负数的出现次数为偶数{ll j=5-i;//i为正数出现次数,j为负数出现次数if(zhengshu.size()>=i&&fushu.size()>=j)//此时结果为正数,我们要使得绝对值尽可能大,这样值更大{ll temp=1;for(ll k=1;k<=i;k++) temp*=zhengshu[zhengshu.size()-k];//正数绝对值大的在末尾for(ll k=0;k<j;k++) temp*=fushu[k];//负数绝对值大的在开头ans=max(ans,temp);}}for(ll i=0;i<5;i+=2)//正数或者0的出现次数为偶数,负数的出现次数为奇数{ll j=5-i;if(zhengshu.size()>=i&&fushu.size()>=j)//此时结果为负数,我们要使得绝对值尽可能小,这样值更大{ll temp=1;for(ll k=0;k<i;k++) temp*=zhengshu[k];//正数绝对值小的在开头for(ll k=1;k<=j;k++) temp*=fushu[fushu.size()-k];//负数绝对值小的在末尾ans=max(ans,temp);}}zhengshu.clear();fushu.clear();cout<<ans<<endl;}
}

C题
树,构造,图结论

题意为,给你一棵n个节点的树,现在从这棵树中取走一个节点,要使得剩下的图中,拥有最大节点数量的树的节点数要尽可能小。
现在不希望这个取走的节点有多种取法,你可以去除掉原树中的一条边,再重连一条边,够成一课新树,使得那个取走的节点取法变为唯一。

这里要先推出来,什么情况下会使得这个取走的节点有多种取法。
这里的结论是,如果有一条边的左右两侧节点数都恰好是n/2(此时n必然是偶数),那么我们分别取走这条边左右两侧的节点,剩下的部分最大节点数均为n/2。

推导这个结论可以用反证法,剩下的部分最大结点数大于n/2的反例就不说明了。
如果剩下的部分最大节点数小于n/2,那么代表取走那个点后,剩下的部分至少有三个,其中一个部分是当前的最大部分有x个结点,另外两个部分分别有y个和z个结点,y<=x,z<=x且x+y+z=n。
取走的这个点是三个部分的连接节点。
那么我们如果不取这个点的话,这三个部分的至少两个部分会连接起来构成一个更大的部分,
由于x+y>x,x+z>x,y+z>x
也就是说我们取其他的点都是会得到比x更大的部分,由此推翻。

寻找这样一条左右两侧节点数均为n/2的“中间边”我们可以通过dfs来得到,那么得到后我们要如何删边加边构造没有这种“中间边”的树呢。
我们注意到这个“中间边”的存在,其实也就是这个子树可以分成两个恰好拥有n/2节点的部分,且两个部分只有一条连边。
我们只需要让它们之间有多条连边即可。
我们用dfs找到这条“中间边”,这条边两侧的点中,u为更接近根节点的点,d为更远离根节点的点。那么我们可以从u的这一侧切出一个点出来(用树根这个点就可以了),把它和d接起来。
这样的话u这一侧就只有n/2-1个点了,再加上d这个点才凑满n/2个点,而d这个点和原本自己一侧至少有一个连边,切下来的原根节点与其又有一条连边,就不再有上述结论的情况了。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const ll maxn=1e5+7;struct Edge
{ll to,next;
}edge[maxn*2];ll head[maxn],ru[maxn],tot,n;//ru[i]数组代表i结点有几条边,用于寻找只有一条边的点作为树根起点
ll u,d;void init()
{for(ll i=1;i<=n;i++) head[i]=-1,ru[i]=0;tot=0;
}void add(ll u,ll v)
{edge[tot].to=v;edge[tot].next=head[u];ru[v]++;head[u]=tot++;
}ll dfs(ll now,ll pre)//dfs返回值为now以及它的子树总共有几个结点,pre为之前的一个节点,用于dfs防止走回头路
{ll ret=1;for(ll i=head[now];i!=-1;i=edge[i].next){ll to=edge[i].to;if(to!=pre) ret+=dfs(to,now);}if(ret==n/2)//如果当前结点的个数恰好等于总结点数的一半,则记录这条“中间边”两侧的两个点位置,u是更接近根节点那一侧的点{u=pre;d=now;}return ret;
}int32_t main()
{IOS;int t;cin>>t;while(t--){cin>>n;init();for(ll i=1;i<n;i++){ll u,v;cin>>u>>v;add(u,v);add(v,u);}if(n&1)//如果总结点数是奇数个则无需进行操作,任意切掉一条边再重新把这条边构造还原即可{ll now=1;ll to=edge[head[now]].to;cout<<now<<' '<<to<<endl;cout<<now<<' '<<to<<endl;}else//如果结点数是偶数个,那么去找是否有哪边边的两侧恰好结点数都是总数的一半,就会出现去除该条边两侧的两个点后,得到的剩余部分的最大结点数相等的情况{//此时最大结点数都是n/2,我们需要构造使得这种情况不再出现ll start=-1;//start为树根节点,挑选只有一条边的叶子作为树根(如果选择树内部而不是叶子作为起点去dfs检测子树节点数量是否等于n/2是不正确的,因为还可能通过树根和其他子树的部分加起来构成n/2的一个子树,以另一个点为树根的情况下)for(ll i=1;i<=n;i++) if(ru[i]==1) start=i;u=d=0;//u为那条“中间边”两侧的点中离根节点较近的点,d为较远的dfs(start,0);//dfs检测是否存在这样一条“中间边”,左右两侧的节点数都是n/2ll to=edge[head[start]].to;//to为与根节点相连的唯一一个点的位置,用于后面构造操作if(u==0)//如果不存在这样的“中间边”则无需操作,任意切掉一条边再重新把这条边构造还原即可{cout<<start<<' '<<to<<endl;cout<<start<<' '<<to<<endl;}else//如果存在这样的“中间边”,从这条边的u那一侧切割下一个点,这里切割下树根节点,然后拼接到另一侧的d点上即可{cout<<start<<' '<<to<<endl;cout<<start<<' '<<d<<endl;}}}
}

D题
贪心,结论,差分

题意为给定一个长度为n的数列A,你需要构造一个长度为n的值不下降的数列B和一个长度为n的值不上升的数列C,满足B[i]+C[i]=A[i]。现在问你数列B和数列C中的最大数值的最小值是多少。

注意到我们只需要关注数列B和C中的最大值,数列B中的最大值是最后一个数字,数列C中的最大值是第一个数字。
我们可以假设固定了数列C中的第一个数字为x,那么数列B中的第一个数字就是A[1]-x。
之后我们依次向后看Ai的值,
如果A[i]<=A[i-1],如果我们仍然按照i-1的位置构造B和C的话,加起来会大于A[i],我们需要减小数字,我们可以直接减少数列C的数字即可,并且不会影响到B和C中的最大值是度搜好。
如果A[i]>A[i-1],如果我们仍然按照i-1的位置构造B和C的话,加起来会小于A[i],我们需要增大数字,我们不能增加数列C的数字值,只能增加数列B的,而这个增加值会影响B中最后一个数字的大小,也就是会影响到最后的最大值。

我们累加A[i]-A[i-1]中大于0的部分,值为temp,那么这样贪心构造后的数列B中的最大值就位A[1]-x+temp,而数列C中的最大值为x,我们希望他们中的最大值尽可能小。也就是两者相加平均分成两部分后较大的那部分了,而两者相加值为A[1]-x+temp+x=A[1]+temp。
因此我们实际上只需要关注第一个位置的数,和后面的数字的差分数组中大于0的部分即可。
我们可以通过差分数组O(1)进行修改操作并得到结果。

另外注意下A[1]+temp是负数的时候,除以2是向上取整的。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;vector<ll>num;int32_t main()
{IOS;int n;cin>>n;num.resize(n+1);for(ll i=1;i<=n;i++) cin>>num[i];ll ans=num[1];for(ll i=n;i>1;i--)//差分操作{num[i]-=num[i-1];if(num[i]>0) ans+=num[i];}cout<<(max(ans/2,ans-ans/2))<<endl;//注意负数除以2是向上取整而不是向下,所以这里这么写是最稳妥的ll q;cin>>q;for(ll i=0;i<q;i++){ll l,r,x;cin>>l>>r>>x;if(l>1){if(num[l]>0) ans-=num[l];if(num[l]+x>0) ans+=num[l]+x;}if(l==1) ans+=x;//ans是num[1]加上后序差分数组大于0的部分,如果改变区间左侧就是1的话,直接要把x加到ans上if(r<n){if(num[r+1]>0) ans-=num[r+1];if(num[r+1]-x>0) ans+=num[r+1]-x;}num[l]+=x;if(r<n) num[r+1]-=x;cout<<max(ans/2,ans-ans/2)<<endl;}
}

Codeforces Round #670 (Div. 2)A-D题解相关推荐

  1. Codeforces Round #670 (Div. 2) C D E

    Codeforces Round #670 Div. 2 C. Link Cut Centroids(dfs树.质心) D. Three Sequences(差分,思维) E . Deleting N ...

  2. Codeforces Round #198 (Div. 2)A,B题解

    Codeforces Round #198 (Div. 2) 昨天看到奋斗群的群赛,好奇的去做了一下, 大概花了3个小时Ak,我大概可以退役了吧 那下面来稍微总结一下 A. The Wall Iahu ...

  3. Codeforces Round #774 (Div. 2)E题题解

    Codeforces Round #774 (Div. 2) E. Power Board 题目陈述 有一个n×m(1≤n,m≤106)n\times m(1\le n,m\le10^6)n×m(1≤ ...

  4. Codeforces Round #640 (Div. 4)(ABCDEG题解)

    文章目录 A. Sum of Round Numbers B - Same Parity Summands C - K-th Not Divisible by n D - Alice, Bob and ...

  5. Codeforces Round #635 (Div. 2)(A~D)题解

    Codeforces #635 A~D A.Ichihime and Triangle B.Kana and Dragon Quest game C.Linova and Kingdom D.Xeni ...

  6. Codeforces Round #670 (Div. 2)

    A - Subset Mex 知道NIM游戏应该都知道Mex.那就直接贪心分组,保证尽可能每组都存在每一个自然数,然后按照Mex定义直接求答案即可 #define IO ios::sync_with_ ...

  7. 【记录CF】Codeforces Round #777 (Div. 2) A~C 题解

    目录 杂谈 A. Madoka and Math Dad B. Madoka and the Elegant Gift C. Madoka and Childish Pranks 杂谈 又是一场离谱掉 ...

  8. Educational Codeforces Round 110 div.2 A~F题解

    视频讲解:BV1254y137Rn A. Fair Playoff 题目大意 有 444 位选手参加比赛,第 iii 位选手的水平为 si(1≤si≤100)s_i(1 \leq s_i \leq 1 ...

  9. Codeforces Round #636 (Div. 3) ——A. Candies 题解

    题目链接:https://codeforces.com/contest/1343/problem/A 签到题,for循环暴力枚举即可. 代码如下: #include <bits/stdc++.h ...

最新文章

  1. CentOS安装KVM步骤虚拟机,绝对实用!
  2. android 获取对象,在Android中获取LayoutInflater对象的方法
  3. spring boot配置对上传文件的大小限制
  4. Java连接Elasticsearch6.xxx 代码高亮显示篇四
  5. 数据挖掘的好书_唐宇迪:入门数据挖掘,我最推荐这本书
  6. UIKit框架之NSObject
  7. SpringCloud的EurekaClient : 客户端应用访问注册的微服务(无断路器场景)
  8. 森林病虫防治系统 (七)
  9. python psutil 获取命令历史_python中系统信息获取psutil使用
  10. python画图显示中文_Python绘图实现显示中文
  11. 小牛uqi几个版本区别_川崎ZX25R便宜版本长这样?
  12. 下载谷歌浏览器官方正式(稳定)版以及历史各种版本
  13. 我为什么放弃网易博客
  14. 自旋锁、阻塞锁、可重入锁、悲观锁、乐观锁、读写锁、偏向所、轻量级锁、重量级锁、锁膨胀、对象锁和类锁
  15. 零基础开发WIFI设备(esp8266)
  16. js获取指定字符前/后的字符串简单实例
  17. excel怎么快速判断录入银行卡号是否正确?
  18. 网络计划法中的最早时间和最迟时间以及关键事件。
  19. python md5加密和统一社会信用代码_统一社会信用代码校验位python实现
  20. Unity3D 实现录音小案例

热门文章

  1. 知识图谱数据库将人类的思维路径转化为机器的路径思维
  2. datax介绍 基于datax官网
  3. 如何快速找到你想要的文献
  4. 计算机大赛颁奖大会,我院举行首届计算机操作员大赛颁奖大会
  5. “21天好习惯”第一期—15
  6. 一文说透 Jarvis+ 去中心化社群经济
  7. 今天是本站参加seo大赛的第二天,博百优的意思解释
  8. adb remount失败问题
  9. android辅助功能失效,app重新安装后无障碍辅助功能失效
  10. 港科夜闻|2021年大湾区科学论坛开幕,香港科大(广州)校长倪明选教授:双校互补,重点发力知识转移创新...