Codeforces Round #535 (Div. 3)

题目总链接:https://codeforces.com/contest/1108

太懒了啊~好久之前的我现在才更新,赶紧补上吧,不能漏掉了。

A. Two distinct points

题意:

给出两个区间的左右边界,输出两个数,满足两个数分别在两个区间内且这两个数不相等。

题解:

直接输出左端点然后判断一下就行了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int q;
int l1,r1,l2,r2;
int main(){
cin>>q;
for(int i=;i<=q;i++){
cin>>l1>>r1>>l2>>r2;
if(l1==l2) l2++;
cout<<l1<<" "<<l2<<endl;
}
return ;
}

B. Divisors of Two Integers

题意:

给出n个数,这n个数都为两个数的因子,最后要求你输出这两个数为什么。

题解:

既然是因子,那么答案也肯定包含在这n个数中,并且因子应该是较大的数。

那么我们排序后从后往前枚举,遇到一个没有被删除的数我们就把它当作我们的答案,并且在其它数中删掉它的因子。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
int n;
int d[N],del[N];
vector <int> vec[N];
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&d[i]);
sort(d+,d+n+);
for(int i=;i<=n;i++){
int x=d[i];
for(int j=;j*j<=x;j++){
if(x%j==){
vec[i].push_back(j);
if(j*j!=x) vec[i].push_back(x/j);
}
}
}
for(int i=n;i>=;i--){
if(del[i]) continue ;
int cnt = ;
while(cnt<vec[i].size()){
for(int j=;j<=i;j++){
if(del[j]) continue ;
if(d[j]==vec[i][cnt]){
cnt++;
del[j]=;
break ;
}
}
}
}
int tot=;
for(int i=;i<=n;i++) if(!del[i]) tot++;
int now = ;
int x=,y=;
for(int i=;i<=n;i++){
if(now==tot-){
if(!del[i]) y*=d[i];
}
else if(!del[i]) x*=d[i],now++;
}
cout<<x<<" "<<y;
return ;
}

C. Nice Garland

题意:

给出一个字符串,这个字符串只由三个大写字母"B","G","R"构成,然后问你最少需要修改多少个字符,可以使得这个串成为一个“好串”。

好串的定义是,对于每一个字符,它和其它相同字符位置相差都为3的倍数。

题解:

因为相差都为3的倍数,那么我们可以断定前三个字符是互不相同的,并且之后每三个字符也是互不相同的。

另外也可以知道,后面的位置与前三个的位置是一一对应的,这样才满足相差为3的倍数这个条件。

那么我们就枚举前三个的所有可能情况,然后根据这个去统计后面需要的修改次数,最后取最小值就行了。

直接枚举太麻烦,所以使用全排列函数next_permutation。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+;
int n;
char s[N],a[N];
char p[]={'R','B','G'};
int main(){
scanf("%d",&n);
scanf("%s",s);
int ans = ;
sort(p,p+);
ans=0x3f3f3f3f3f;
int tot=;
do{
tot++;
int cnt = ;
for(int i=;i<min(n,);i++){
if(p[i]!=s[i]) cnt++;
}
for(int i=;i<n;i++){
if(p[i%]!=s[i]) cnt++;
}
if(ans>cnt){
ans=cnt;
for(int i=;i<;i++) a[i]=p[i];
}
}while(next_permutation(p,p+));
cout<<ans<<endl;
for(int i=;i<n;i++) cout<<a[i%];
return ;
}

D. Diverse Garland

题意:

还是给出一个只由"R","G","B"构成的字符串,现在问最少的修改次数使得两两相邻的字符不想等为多少。

题解:

这题可以dp吧,但是我是直接贪心来做的。

直接这样想,对于一段连续且相等的串,我们只需要改变其偶数位置就行了。注意一下改变的时候不要和前面以及后面的相等了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+;
int n;
char s[N],p[N];
char a[N]={'R','B','G'};
void change(int x){
for(int i=;i<;i++){
p[x]=a[i];
if(p[x]!=s[x-] && p[x]!=s[x+]) return ;
}
return ;
}
int main(){
scanf("%d",&n);
scanf("%s",s+);
int ans = ;
int tot=;
for(int i=;i<=n;i++) p[i]=s[i];
for(int i=;i<=n;i++){
if(s[i]!=s[i-]) tot=;
else{
tot++;
if(tot%==){
change(i);
ans++;
}
}
}
cout<<ans<<endl;
for(int i=;i<=n;i++) cout<<p[i];
return ;
}

E1. Array and Segments (Easy version)

题意:

给出n个数ai以及m个区间,现在要求你选择一些区间,然后每个区间里面的所有数减去1,最后问选择区间过后,n个数中最大值减去最小值最大为多少。

题解:

简单版本的数据范围比较小,直接暴力就行了。

暴力的话考虑枚举最后最小的位置是哪一个,然后就选择所有覆盖这个点的区间,暴力计算就ok。

代码如下:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = ,M = ;
int a[N],mx[N],mn[N],b[N];
struct seg{
int l,r,id;
bool operator < (const seg &A)const{
return r<A.r;
}
}p[M];
int n,m;
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
for(int i=;i<=m;i++) scanf("%d%d",&p[i].l,&p[i].r),p[i].id=i;
sort(p+,p+m+);
memset(mn,INF,sizeof(mn));
for(int i=;i<=n+;i++) mx[i]=-INF;
for(int i=n;i>=;i--)
mx[i]=max(mx[i+],a[i]);
for(int i=n;i>=;i--)
mn[i]=min(mn[i+],a[i]);
int ans = mx[]-mn[];
int num=;
for(int i=;i<=n;i++){
for(int j=;j<=n;j++) a[j]=b[j];
for(int j=;j<=m;j++){
if(p[j].l<=i && p[j].r>=i){
for(int k=p[j].l;k<=p[j].r;k++) a[k]--;
}
}
int minx = INF,maxx = -INF;
for(int j=;j<=n;j++) minx=min(minx,a[j]),maxx=max(maxx,a[j]);
if(ans<maxx-minx){
ans=maxx-minx;
num=i;
}
}
cout<<ans<<endl;
int tot=;
vector <int> vec;
for(int i=;i<=m;i++){
if(p[i].l<=num && p[i].r>=num) tot++,vec.push_back(p[i].id);
}
cout<<tot<<endl;
for(auto v:vec) cout<<v<<" ";
return ;
}

E2. Array and Segments (Hard version)

题意:

这题和E1的题目描述都是一样的,不同的就是数据范围变大了,现在是n<=1e5,m<=300,显然不能直接暴力枚举每个最小值了。

题解:

区间个数还是那么多,注意到区间个数比n小很多,那么我们可以考虑离散化,这样数轴上最多只剩下600个点,然后我们记录一下每一段的最大最小值。

这样段数也只有最多600个,区间还是300个,暴力枚举就不会超时了。

为啥可以把每一段看成点呢?因为对于被区间“分隔”的每一段区间,它们所拥有的区间覆盖都是相同的,这个画下图就知道了。

给出代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5+,M = ;
int a[N],l[N],r[N],b[N],c[N];
int n,m,tot;
int mx[N],mn[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=m;i++){
scanf("%d%d",&l[i],&r[i]);
r[i]++;
b[++tot]=l[i];
b[++tot]=r[i];
}
b[++tot]=;b[++tot]=n+;
sort(b+,b+tot+);
tot = unique(b+,b+tot+)-(b+);
for(int i=;i<=m;i++){
l[i]=lower_bound(b+,b+tot+,l[i])-b;
r[i]=lower_bound(b+,b+tot+,r[i])-b;
}
int t1=-INF,t2=INF;
for(int i=;i<tot;i++){
mx[i]=mn[i]=a[b[i]];
for(int j=b[i]+;j<b[i+];j++){
mx[i]=max(mx[i],a[j]);
mn[i]=min(mn[i],a[j]);
}
t1=max(t1,mx[i]);t2=min(t2,mn[i]);
}
vector <int> ans[N];
int Ans=t1-t2,pos=;
for(int x=;x<tot;x++){
memset(c,,sizeof(c));
for(int j=;j<=m;j++){
if(l[j]<=x && r[j]>x)
ans[x].push_back(j);
}
if(!ans[x].size()) continue ;
for(auto v:ans[x]){
c[l[v]]--;c[r[v]]++;
}
int s = ,minx = INF,t=,maxx=-INF;
for(int i=;i<tot;i++){
s+=c[i];
if(!t || mn[i]+s<minx) minx=mn[t=i]+s;
}
s = ;
for(int i=;i<tot;i++){
s+=c[i];
if(mx[i]+s>maxx) maxx=mx[i]+s;
}
if(maxx-minx>Ans){
Ans=maxx-minx;
pos=x;
}
}
cout<<Ans<<endl<<ans[pos].size()<<endl;
for(auto v:ans[pos]) cout<<v<<" ";
return ;
}

还有一种更巧妙地解法,用不上离散化,直接搞就是了。

就是还是从1~n进行枚举,只有当前点为某个区间的端点时进行更新,然后再暴力求最大最小值来计算。

这个复杂度是O(n*m)的。

代码如下:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5+,M = ;
int n,m;
int a[N],b[N],l[N],r[N];
vector <int> pl[N],pr[N];
int main(){
cin>>n>>m;
int mx = -INF ,mn= INF;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
mx=max(mx,a[i]);
mn=min(mn,a[i]);
}
for(int i=;i<=m;i++){
scanf("%d%d",&l[i],&r[i]);
pl[l[i]].push_back(i);
pr[r[i]+].push_back(i);
}
int ans = mx-mn,pos=-,tmp;
for(int i=;i<=n;i++){
int len1=pl[i].size(),len2=pr[i].size();
if(len1){
for(auto v:pl[i]){
for(int j=l[v];j<=r[v];j++) a[j]--;
}
}
if(len2){
for(auto v:pr[i]){
for(int j=l[v];j<=r[v];j++) a[j]++;
}
}
if(len1 || len2){
mx = -INF,mn = INF;
for(int i=;i<=n;i++){
mx=max(mx,a[i]);
if(a[i]<mn){
mn=a[i];
tmp=i;
}
if(mx-mn>ans){
ans=mx-mn;
pos=tmp;
}
}
}
}
cout<<ans<<endl;
int cnt = ;
for(int i=;i<=m;i++){
if(l[i]<=pos && r[i]>=pos) cnt++;
}
cout<<cnt<<endl;
for(int i=;i<=m;i++){
if(l[i]<=pos && r[i]>=pos) cout<<i<<" ";
}
return ;
}

F. MST Unification

题意:

给出一个无向图,每条边有相应边权,然后现在你可以对某些边的边权加上一个值。

现在问你最少需要多少次操作,可以使得这个图的最小生成树唯一。

题解:

这个思路还是挺巧妙的,也是求最小生成树。我们假设目前边权为x的边有c条,那么我们先剔除不用的边a,再尽可能地在途中加边b,最后的c-a-b条边就是我们需要对其进行操作的边。

然后稍微修改一下Kruskal就行了,具体见代码吧:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+;
int n,m;
int f[N];
struct Edge{
int u,v,w;
bool operator <(const Edge &A)const{
return w<A.w;
}
}e[N];
int find(int x){
return f[x]==x ? f[x] : f[x]=find(f[x]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[i]={u,v,w};
}
sort(e+,e+m+);
for(int i=;i<=n+;i++) f[i]=i;
int ans = ;
for(int i=,j=;i<=m;i=j){
while(e[i].w==e[j].w) j++;
int cnt = j-i;
for(int k=i;k<j;k++){
int fx=find(e[k].u),fy=find(e[k].v);
if(fx==fy) cnt--;
}
for(int k=i;k<j;k++){
int fx=find(e[k].u),fy=find(e[k].v);
if(fx==fy) continue ;
cnt--;
f[fx]=fy;
}
ans+=cnt;
}
cout<<ans;
return ;
}

这份题解总算写完了~还有几个找时间再补吧。

Codeforces Round #535 (Div. 3) 题解的更多相关文章

  1. Codeforces Round #182 (Div. 1)题解【ABCD】

    Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...

  2. Codeforces Round #608 (Div. 2) 题解

    目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...

  3. Codeforces Round #525 (Div. 2)题解

    Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...

  4. Codeforces Round #528 (Div. 2)题解

    Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...

  5. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  6. Codeforces Round #677 (Div. 3) 题解

    Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...

  7. Codeforces Round #665 (Div. 2) 题解

    Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...

  8. Codeforces Round #160 (Div. 1) 题解【ABCD】

    Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...

  9. Codeforces Round #383 (Div. 2) 题解【ABCDE】

    Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...

随机推荐

  1. linux网络服务实验

    1.设置window IP地址为192.168.3.XX,掩码24位. 2.设置Linux IP地址为192.168.3.YY,掩码24位.window与Linux互相ping通. 3.在linux中 ...

  2. ABAP CDS ON HANA-(11)ABAP CDSでの関連付け

    Association in ABAP CDS An association in CDS view joins different data sources. Defining and using ...

  3. 【转载】[Elasticsearch]ES入门

    传送门:http://www.cnblogs.com/xing901022 ES即简单又复杂,你可以快速的实现全文检索,又需要了解复杂的REST API.本篇就通过一些简单的搜索命令,帮助你理解ES的 ...

  4. iOS中的数据库应用

    iOS中的数据库应用 SLQLite简介 什么是SQLite SQLite是一款轻型的嵌入式数据库 它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 它的处理速度比Mysql.Post ...

  5. django中判断当前user具有是否有对模块的增删改查权限

    首先简单了解一下user的一些属性 User对象 User对象是认证系统的核心.用户对象通常用来代表网站的用户,并支持例如访问控制.注册用户.关联创建者和内容等.在Django认证框架中只有一个用户类 ...

  6. 孤荷凌寒自学python第六十九天学习并实践beautifulsoup对象用法2

    孤荷凌寒自学python第六十九天学习并实践beautifulsoup对象用法2 (完整学习过程屏幕记录视频地址在文末) 今天继续学习beautifulsoup对象的属性与方法等内容. 一.今天进一步 ...

  7. LeetCode 全解(bug free 训练)

    1.Two Sum Given an array of integers, return indices of the two numbers such that they add up to a s ...

  8. PyQt5图像全屏显示

    Windows装这个:https://pypi.python.org/pypi/PyQt5Ubuntu输入这个:sudo apt-get install python3-pyqt5 或者直接输入:pi ...

  9. BZOJ 1010 HNOI2008 玩具装箱 斜率优化

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1010 Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的 ...

  10. BZOJ 3670 NOI2014 动物园 KMP+dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3670 题意概述:令num[i]表示字符串由1~i的字符形成的前缀中不相重叠的相同前后缀的数 ...