您的位置:首页 > 其它

CodeForces #575 div3

2020-02-02 19:45 155 查看

Div3还是比较水的…都是基本都是思维题,只涉及到很少的算法.

A. Three Piles of Candies

叽里呱啦说了一大堆,其实就是让求三个数的平均值…

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
ll a,b,c;
scanf("%d",&n);
while(n--)
{
scanf("%lld%lld%lld",&a,&b,&c);
ll d=a+b+c;
printf("%lld\n",d/2);
}
return 0;
}

B. Odd Sum Segments

题意就是给一串数字,随便划分k个区间,问每个小区间的和是否和为奇数,如果是奇数,就输出yes,然后每个区间的末位置,如果不是就输出no
这个题应该是一个数论的问题.做这个题之前首先得先想到一个问题,那就是只有奇数个奇数相加和才是奇数。就像(1+1+1),而偶数个奇数相加是偶数,而这一个偶数的个数并不影响结果,所以我们就直接考虑奇数的位置和个数就好.详情请见代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[222222];
int b[222222];   //用来标记存奇数所在的位置
ll q,n,k;
int main()
{
//ios::sync_with_stdio(false);
cin>>q;
while(q--)
{
ll x=0;
ll y=0;
//memset(b,0,sizeof b);
cin>>n>>k;
for(int i=0;i<n;i++)
b[i]=0;
//int f=0;
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
if(a[i]&1)
b[x++]=i;
}
if(x<k)  //如果奇数个数小于区间数朱姐输出no
{
cout<<"NO"<<endl;
continue;
}
else
{
if((x-k+1)%2==0) //出现一个奇数划分一个区间,如果第k-1个区间有偶数个奇数,则肯定不满足,输出no
cout<<"NO"<<endl;
else         		//剩余的情况都是可以的,直接输出来就好,注意格式
{
cout<<"YES"<<endl;
int tt=0;
for(int i=0;i<x;i++)
{
if(tt!=k-1)
{
printf("%d ",b[i]+1);
//cout<<b[i]+1<<" ";
tt++;
}
else
{
cout<<n<<endl;
break;
}
}
}
}
}
return 0;
}

C. Robot Breakout

//题意就是给定坐标上的一堆机器人,然后他的有的有故障,不能向某个方向移动(后四个数,哪个为0就不能向哪边移动),问最后这些机器人能不能移动到一个点上。如果可以的话,就随便输出一个点。

思路:先把最开始的最大的面积的坐标标记出来,然后按照给定的移动方向缩小面积,最后随便输出一个边界点!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
ios::sync_with_stdio(false);
int q; cin>>q;
int x,y,a,b,c,d;

while(q--)
{
int flag=1;
int n;	cin>>n;
int xx1,xx2,xx3,xx4,yy1,yy2,yy3,yy4;
xx1=xx2=100000;
xx4=xx3=-100000;
yy1=yy4=100000;
yy2=yy3=-100000;   //四个角的四个坐标
while(n--)
{
cin>>x>>y>>a>>b>>c>>d;
if(flag)
{
if(a==0) //代表不能向左移动,所以左边的边取最大的x,下边同理
{
xx3=max(xx3,x);
xx4=max(xx4,x);
}
if(b==0)
{
yy1=min(y,yy1);
yy4=min(y,yy4);
}
if(c==0)
{
xx1=min(x,xx1);
xx2=min(x,xx2);
}
if(d==0)
{
yy2=max(y,yy2);
yy3=max(y,yy3);
}
}

if(xx3>xx2||yy3>yy4)//移动后冲突了,则代表不行
flag=0;
}
if(flag)
cout<<1<<" "<<xx3<<" "<<yy3<<endl;
else
cout<<0<<endl;

}

return 0;
}

D1. RGB Substring (easy version)

思路:由于是easy,所以暴力所有情况肯定能过…

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,q,k;
char s[22222];
int p(int a)
{
int b=a+k-1;
int x=0;
int y=0;
int z=0;
for(int i=a;i<=b;i=i+3)
if(s[i]!='R')
x++;
for(int i=a+1;i<=b;i=i+3)
if(s[i]!='G')
x++;
for(int i=a+2;i<=b;i=i+3)
if(s[i]!='B')
x++;

for(int i=a;i<=b;i=i+3)
if(s[i]!='G')
y++;
for(int i=a+1;i<=b;i=i+3)
if(s[i]!='B')
y++;
for(int i=a+2;i<=b;i=i+3)
if(s[i]!='R')
y++;

for(int i=a;i<=b;i=i+3)
if(s[i]!='B')
z++;
for(int i=a+1;i<=b;i=i+3)
if(s[i]!='R')
z++;
for(int i=a+2;i<=b;i=i+3)
if(s[i]!='G')
z++;
return min(x,min(y,z));
}
int main()
{
ios::sync_with_stdio(false);
cin>>q;
while(q--)
{
int zz=0;
int xx=999999;
cin>>n>>k>>s+1;
for(int i=1;i<=n-k+1;i++)
{
int zz=p(i);
xx=min(xx,zz);
}
cout<<xx<<endl;
}
return 0;
}

D2. RGB Substring (hard version)

题意和上边的一模一样,但是这个是hard…所以不能暴力了。不过仔细考虑一下还是很简单的,就是一个前缀和的更新和处理…和暴力的思路还是很像的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char str[2222222];
char t[222222];
int a[222222],sum[222222];
int main()
{
ios::sync_with_stdio(false);
int q;	cin>>q;
while(q--)
{
int ans=999999999;
int n,k;
cin>>n>>k>>str+1;
for(int i=1;i<=n+4;i=i+3)   //把t数组都更新为RGBRGB.....
{
t[i]='R';
t[i+1]='G';
t[i+2]='B';
}

for(int j=1;j<=3;j++)  //先从R,再从G,再从B依次统计
{
for(int i=1;i<=n;i++)
{
if(t[i+j-1]!=str[i])
a[i]=1;
else
a[i]=0;
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];  //求前缀和

for(int i=k;i<=n;i++)    //统计区间从X->X+k总共更新了几次
ans=min(ans,sum[i]-sum[i-k]);
}
cout<<ans<<endl;
}
return 0;
}

E. Connected Component on a Chessboard

题意:就是给定一个好大的棋盘(这个棋盘是一黑一白相邻的)…然后问有没有一个连续的区域里面包含b个黑方块,w个白方块,有的话,随便输出这个区域的所有坐标,没有的话就输出NO。
思路:实在是没办法了,暴力了一下,没想到A了…就是,如果max(b,w)>min(b,w)*3+1,肯定没答案…
其余的情况都是有答案的,先先选一行,把min(b,w)*2全部输出,然后把剩下的一次放在这一行的上一行和下一行…详情请见代码…

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int b,w;
int main()
{
//ios::sync_with_stdio(false);
int q;	scanf("%d",&q);
while(q--)
{
scanf("%d%d",&b,&w);
int aa=min(b,w);
int bb=max(b,w);
if(bb>aa*3+1)
{
printf("NO\n");
}
else
{
if(b==w)
{
printf("YES\n");
for(int i=1;i<=b+w;i++)
printf("1 %d\n",i);
}
else if(b<w)  //白色的多,就得从白色的那个放起,(防止4白1黑这种)
{
printf("YES\n");
for(int i=2;i<=b*2+2;i++)
printf("4 %d\n",i);   //随便选了第四行
w=w-b-1;
if(w)				//白色有剩余就把它放在第三行
{
for(int i=3;i<=b*2+2;i=i+2)
{
printf("3 %d\n",i);
w--;
if(w==0)
break;
}

}
if(w)      //还有剩余就放在第五行
{
for(int i=3;i<=b*2+2;i=i+2)
{
printf("5 %d\n",i);
w--;     //放一颗剩余的白棋少一颗
if(w==0)  //放完的话就跳出循环,不用再继续输出了
break;
}
}
}
else if(b>w)   //与上边同理,同样要注意(4黑1白这种情况)
{
printf("YES\n");
for(int i=3;i<=w*2+3;i++)
printf("4 %d\n",i);
b=b-w-1;
if(b)
{
for(int i=4;i<=w*2+3;i=i+2)
{
printf("3 %d\n",i);
b--;
if(b==0)
break;
}
}
if(b)
{
for(int i=4;i<=w*2+3;i=i+2)
{
printf("5 %d\n",i);
b--;
if(b==0)
break;
}
}
}
}
}
return 0;
}

F. K-th Path

题意:给定一个无向图,求第K短路径的长度。
自己没想出来,看的网上的题解,只需要保留k条边,这样已经有了k个点对的距离小于排好序后第k条边的距离。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;

const int maxn=2e5+5;

struct edge
{
int from,to;
ll dis;
}Edge[maxn];

bool cmp(edge a,edge b)
{
return a.dis<b.dis;
}
vector<ll> vec;
ll a[805],s[805][805];
int len,n,m,k;

void floyd()
{
for(int k=1;k<=len;k++)
for(int i=1;i<=len;i++)
for(int j=1;j<=len;j++)
s[i][j]=min(s[i][j],s[i][k]+s[k][j]);
}

int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<m;i++)
scanf("%d%d%lld",&Edge[i].from,&Edge[i].to,&Edge[i].dis);
sort(Edge,Edge+m,cmp);    //把边从小到大排序
for(int i=0;i<k;i++)
{
a[len++]=Edge[i].from;
a[len++]=Edge[i].to;
}

sort(a,a+len);

len=unique(a,a+len)-a;    //去重函数,建议去学,挺高大尚的,第二次用了
//	for(int i=0;i<=len;i++)
//		cout<<a[i]<<" ";
for(int i=1;i<=len;i++)   //初始化另一幅图
for(int j=1;j<=len;j++)
s[i][j]=1e16;
int t1,t2;
for(int i=0;i<k;i++)
{
t1=upper_bound(a,a+len,Edge[i].from)-a;  //建议去学这个真香函数,这里要注意,当大于范围内的数,就
t2=upper_bound(a,a+len,Edge[i].to)-a;//返回n+1的位置,刚好巧妙的利用了这点,这里的Edge是排好序的
//cout<<endl<<t1<<" "<<t2;
s[t1][t2]=s[t2][t1]=Edge[i].dis;     //存图
}
floyd();
for(int i=1;i<=len;i++)
for(int j=i+1;j<=len;j++)
if(s[i][j]!=1e16)
vec.push_back(s[i][j]);
sort(vec.begin(),vec.end());   //排序输出第k小
printf("%lld\n",vec[k-1]);
return 0;
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
〆℡小短腿走快点ゝ 发布了30 篇原创文章 · 获赞 1 · 访问量 1409 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: