Codeforces Round #619 (Div. 2)
A. Three Strings
题意:给三个长度相同的非空字符串abc,依次将c中的每个字符和a或者b中对应位置的字符进行交换,交换必须进行,问能否使得ab相同。
思路:对于每一个位置,如果三个字符都不相同,那一定不同,如果有两个相同且不是ab相同,则合法,否则不合法,如果三个字符都相同,那么合法。
#include<bits/stdc++.h>
#define LL long long
#define dl double
void rd(int &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
void lrd(LL &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
const int INF=1e9;
const LL LINF=1e18;
const int inf=;
using namespace std;
int T;
char a[inf],b[inf],c[inf];
bool check(int x){
if(a[x] == b[x])return a[x] != c[x];
if(a[x] == c[x] || b[x] == c[x])return ;
return ;
}
int main(){
// freopen("in.txt","r",stdin);
rd(T);
while(T--){
scanf("%s%s%s",a,b,c);
int n=strlen(a),flg=;
for(int i=;i<n;i++)
if(check(i))flg=;
if(flg)printf("NO\n");
else printf("YES\n");
}
return ;
}
/**/
B. Motarack's Birthday
题意:给一串数,一些位置没有数字,选择一个数填到所有空位上,使得相邻两数之差的绝对值的最大值最小。
思路:找出旁边有空位的数字中最大的和最小的,相加除二便可以得到使得空位和非空位之间差的绝对值的最大值最小的数,再统计一下非空位之间的贡献即可。
#include<bits/stdc++.h>
#define LL long long
#define dl double
void rd(int &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
void lrd(LL &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
const int INF=1e9;
const LL LINF=1e18;
const int inf=1e5+;
using namespace std;
int T,n;
int a[inf];
int mx,mn;
int main(){
/// freopen("in.txt","r",stdin);
rd(T);
while(T--){
rd(n);mx=;mn=1e9+;
for(int i=;i<=n;i++)rd(a[i]);
for(int i=;i<n;i++){
if(a[i] == -)continue;
if(a[i-] == - || a[i+] == -)mx=max(mx,a[i]),mn=min(mn,a[i]);
}
if(a[] != - && a[] == -)mx=max(mx,a[]),mn=min(mn,a[]);
if(a[n] != - && a[n-] == -)mx=max(mx,a[n]),mn=min(mn,a[n]);
int ans1,ans2;ans2=(mn+mx)/;
if(mx)ans1=max(mx-ans2,ans2-mn);else ans1=;
for(int i=;i<n;i++)if(a[i]!=- && a[i+]!=-)ans1=max(ans1,abs(a[i+]-a[i]));
printf("%d %d\n",ans1,ans2);
}
return ;
}
/**/
C. Ayoub's function
题意:定义f(s)表示01串s中包含至少一个1的连续子串的数目,求长度为n且有m个1的01串中f(s)的最大值。
思路:一共有n*(n-1)/2个子串,我们只需要求出一个1都不包括的子串的数目的最小值即可得到答案。可以发现只需要对连续的0串进行统计即可,答案为(l-1)*l/2,容易发现使得0串长度尽可能平均会使得答案最小,于是将其分为相等的m+1组,多出来的再一个一个分配给每一组,这样就得到了所有0串的长度,统计答案即可。
#include<bits/stdc++.h>
#define LL long long
#define dl double
void rd(int &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
void lrd(LL &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
const int INF=1e9;
const LL LINF=1e18;
using namespace std;
int T;
int n,m;
int main(){
// freopen("in.txt","r",stdin);
rd(T);
while(T--){
rd(n),rd(m);
LL ans=;
if(n == m)ans=1ll*n*(n+)/;
else if(!m)ans = ;
else {
int u=(n-m)/(m+),v=(n-m)%(m+);
ans+=1ll*(m+-v)*u*(u+)/;
ans+=1ll*v*(u+)*(u+)/;
ans=1ll*n*(n+)/-ans;
}
printf("%lld\n",ans);
}
return ;
}
/**/
D. Time to Run
题意:nm的格子,相邻格子之间有两条相反的单向路,从11开始沿着路走,可以在任意一个格子结束,每条路只能走一次,问能否走k条路,并输出方案。
思路:可以发现应该存在一个可以走的路的最大值,大胆猜测存在一种方式可以一次走完所有的路,构造可以发现,一直往右,然后下,一直往左,然后下,直到最后一行,然后上下左(右)重复到边界,往上走,继续重复即可一次走完所有的路。需要注意输出有要求,需要对一些步骤进行压缩,可以证明压缩后一定在3000以内。还需要注意处理单列的情况。
#include<bits/stdc++.h>
#define LL long long
#define dl double
void rd(int &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
void lrd(LL &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
const int INF=1e9;
const LL LINF=1e18;
const int inf=;
using namespace std;
int n,m,k;
struct ghb{
int x;
char s[];
}sta[inf];
int top;
int main(){
// freopen("in.txt","r",stdin);
// freopen("a.out","w",stdout);
rd(n);rd(m);rd(k);
if(*n*m-*n-*m < k)printf("NO\n");
else {
printf("YES\n");
for(int i=;i<=n;i++){
if(!k)break;
if(i & ){
if(k <= m-){sta[++top]=(ghb){k,"R"};k=;break;}
k-=m-;if(m-)sta[++top]=(ghb){m-,"R"};
}
else {
if(k <= m-){sta[++top]=(ghb){k,"L"};k=;break;}
k-=m-;if(m-)sta[++top]=(ghb){m-,"L"};
}
if(k && i != n)sta[++top]=(ghb){,"D"},k--;
}
for(int i=n;i>;i--){
if(!k)break;
if(i & ){
if(k <= (m-)*){
int tmp1=k/,tmp2=k%;
if(tmp1)sta[++top]=(ghb){tmp1,"UDL"};
if(tmp2 == )sta[++top]=(ghb){,"U"};
if(tmp2 == )sta[++top]=(ghb){,"UD"};
k=;break;
}
if(m-)sta[++top]=(ghb){m-,"UDL"};k-=(m-)*;
}
else {
if(k <= (m-)*){
int tmp1=k/,tmp2=k%;
if(tmp1)sta[++top]=(ghb){tmp1,"UDR"};
if(tmp2 == )sta[++top]=(ghb){,"U"};
if(tmp2 == )sta[++top]=(ghb){,"UD"};
k=;break;
}
if(m-)sta[++top]=(ghb){m-,"UDR"};k-=(m-)*;
}
if(k)k--,sta[++top]=(ghb){,"U"};
}
if(k)sta[++top]=(ghb){k,"L"};
printf("%d\n",top);
for(int i=;i<=top;i++)printf("%d %s\n",sta[i].x,sta[i].s);
}
return ;
}
/**/
反思:遇到这种明显存在一个分界点的题,应该大胆猜想分界点是那个最特殊的点,nm格子这种题要单独考虑单行单列的情况。
E. Nanosoft
题意:定义一个logo是一个正方形,左上部分是红色,右上部分是绿色,左下部分是黄色,右下部分是蓝色,给一个nm的图,q次询问每次询问一个矩形区间内最大的logo有多大。
思路:首先可以考虑找出所有logo的位置,可以枚举中心,一层一层往外"剥",这样可以在nm时间复杂度内预处理出来,并可以得到他们的大小。考虑每次询问,试想我们从外往里一层一层剥,记录剥掉的层数k,再求出内部所有logo中心位置的logo大小的最大值,二者取较小值便可以得到一个小于等于答案的数,当内部的答案对应logo中心在最外层时便可以使得求出的值等于答案(当然其他的k也可能对应答案),区间最大值用二维st表解决即可,需要注意有很多边界的细节问题,此时时间复杂度已经合适,但有更优的解法,因为我们可以发现内部最大值随层数k的增加是递减的,同时得到最终答案的时候层数k一定是小于等于内部最大值的,所以应该找到尽可能大的k,所以可以二分答案找到满足k小于等于内部最大值的最大的k。需要注意上述说明中的小于或是大于之类的字眼都可能存在+1-1再比较大小的情况,因为我的代码中是取中心的左上角作为真正的中心,导致后面很多地方都需要+1-1之类的细节,具体情况画图即可得知。
#include<bits/stdc++.h>
#define LL long long
#define dl double
void rd(int &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
void lrd(LL &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
const int INF=1e9;
const LL LINF=1e18;
const int N=;
using namespace std;
int n,m,q;
char s[N][N];
int a[N][N];
int work(int x,int y,int z){
for(int i=;i<z;i++)if(s[x][y+i] != 'R' || s[x+*z-][y+i] != 'Y' || s[x+i][y] != 'R' || s[x+i][y+*z-] != 'G')return z-;
for(int i=z;i<*z;i++)if(s[x][y+i] != 'G' || s[x+*z-][y+i] != 'B' || s[x+i][y] != 'Y' || s[x+i][y+*z-] != 'B')return z-;
if(x > && y > && x+*z <= n && y+*z <= m)return work(x-,y-,z+);else return z;
}
int st[N][N][][];
int f[N];
int get_ans(int x1,int y1,int x2,int y2){
if(x1 > x2 || y1 > y2)return ;
int hx=f[x2-x1+],hy=f[y2-y1+];
return max(max(st[x1][y1][hx][hy],st[x1][y2-(<<hy)+][hx][hy]),max(st[x2-(<<hx)+][y1][hx][hy],st[x2-(<<hx)+][y2-(<<hy)+][hx][hy]));
}
int main(){
// freopen("in.txt","r",stdin);
rd(n);rd(m);rd(q);
for(int i=;i<=n;i++)scanf("%s",s[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
a[i][j]=work(i,j,);
f[]=-;for(int i=;i<=max(n,m);i++)f[i]=f[i>>]+;
for(int i=;(<<i) <= n;i++)
for(int j=;(<<j) <= m;j++)
for(int x=;x+(<<i)- <= n;x++)
for(int y=;y+(<<j)- <= m;y++){
if(!i && !j)st[x][y][i][j]=a[x][y];
else if(!i)st[x][y][i][j]=max(st[x][y][i][j-],st[x][y+(<<j-)][i][j-]);
else st[x][y][i][j]=max(st[x][y][i-][j],st[x+(<<i-)][y][i-][j]);
}
for(int i=;i<=q;i++){
int x1,y1,x2,y2;rd(x1);rd(y1);rd(x2);rd(y2);x2--;y2--;
if(x2 < x1 || y2 < y1){printf("0\n");continue;}
int l=,r=min(x2-x1+,y2-y1+)/;
while(l != r){
int mid=(l+r>>)+;
if(get_ans(x1+mid,y1+mid,x2-mid,y2-mid) >= mid+)l=mid;
else r=mid-;
}
int tmp=min(get_ans(x1+l,y1+l,x2-l,y2-l),l+);
printf("%d\n",*tmp*tmp);
}
return ;
}
/**/
反思:一种解题的新思路吧,通过加上一种限定来使得当前答案可求,而这种限定甚至可以用二分优化。
F. Super Jaber
题意:nm格子,每个格子有颜色,颜色最多40种,每一步可以上下左右或者从当前格子跳到任意一个颜色相同的其他格子,q次询问两点之间的最短距离。
思路:如果不同色跳,那么横纵坐标差的绝对值加和即为答案,如果进行同色跳,不妨枚举用其中一次是哪一种同色跳,这就需要我们处理出每种颜色离一个点最近距离是多少,按颜色bfs,将所有该颜色点一次推入,用两种方式转移,需要注意同色跳操作在对于每种颜色预处理时每一种颜色至多一次(需要直接特判掉不然枚举的复杂度会很高)。
#include<bits/stdc++.h>
#define LL long long
#define dl double
void rd(int &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
void lrd(LL &x){
x=;int f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<='' && ch>='')x=x*+ch-'',ch=getchar();x*=f;
}
const int INF=1e9;
const LL LINF=1e18;
const int N=;
const int K=;
using namespace std;
int n,m,k,q;
int a[N][N];
int dis[N][N][K];
struct Point{
int x,y;
};
queue<Point>S;
int dx[]={,-,,},dy[]={,,,-};
vector<Point>T[K];
bool tag[K];
void get_dis(int x){
for(int i=;i<T[x].size();i++)S.push(T[x][i]),dis[T[x][i].x][T[x][i].y][x]=;
memset(tag,,sizeof(tag));
while(!S.empty()){
Point u=S.front();S.pop();
for(int i=;i<;i++){
int tx=dx[i]+u.x,ty=dy[i]+u.y;
if(tx < || tx > n || ty < || ty > m || dis[tx][ty][x] != 0x3f3f3f3f)continue;
dis[tx][ty][x]=dis[u.x][u.y][x]+;S.push((Point){tx,ty});
}
int col=a[u.x][u.y];
if(!tag[col]){
tag[col]=;
for(int i=;i<T[col].size();i++)
if(dis[T[col][i].x][T[col][i].y][x] == 0x3f3f3f3f)
dis[T[col][i].x][T[col][i].y][x]=dis[u.x][u.y][x]+,S.push(T[col][i]);
}
}
}
int main(){
// freopen("in.txt","r",stdin);
rd(n);rd(m);rd(k);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)rd(a[i][j]),T[a[i][j]].push_back((Point){i,j});
memset(dis,0x3f,sizeof(dis));for(int i=;i<=k;i++)get_dis(i);rd(q);
for(int i=;i<=q;i++){
int r1,c1,r2,c2;rd(r1);rd(c1);rd(r2);rd(c2);
int ans=abs(r1-r2)+abs(c1-c2);
for(int j=;j<=k;j++)ans=min(ans,dis[r1][c1][j]+dis[r2][c2][j]+);
printf("%d\n",ans);
}
return ;
}
/**/
反思:这使我回忆起了一个很常见好用的套路,即预处理部分,"求出距离当前点最近被标记点",这种可以通过一次性将所有被标记的点推入队列进行bfs得到。
Codeforces Round #619 (Div. 2)的更多相关文章
- Codeforces Round #619 (Div. 2)E思维+二维RMQ
题:https://codeforces.com/contest/1301/problem/E 题意:给个n*m的图形,q个询问,每次询问问询问区间最大的合法logo的面积是多少 分析:由于logo是 ...
- Codeforces Round #619 (Div. 2) A~D题解
最近网课也开始了,牛客上一堆比赛题目也没补,所以就D题后面的也懒得补了 A.Three String 水题 #include <cstdio> #include <cstring&g ...
- Codeforces Round #619 (Div. 2)D(模拟)
先把一种最长路线记录下来,根据k的大小存到ans中相应的答案再输出 #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using n ...
- Codeforces Round #619 (Div. 2)C(构造,容斥)
#define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using namespace std; int main(){ ios::syn ...
- Codeforces Round #619 (Div. 2) Ayoub's function
Ayoub thinks that he is a very smart person, so he created a function f(s)f(s) , where ss is a binar ...
- Codeforces Round #619 (Div. 2) B. Motarack's Birthday
Dark is going to attend Motarack's birthday. Dark decided that the gift he is going to give to Motar ...
- Codeforces Round #619 (Div. 2) A. Three Strings
You are given three strings aa , bb and cc of the same length nn . The strings consist of lowercase ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
随机推荐
- Linux命令:grep命令 | egrep命令
grep:文本搜素工具,根据用户指定的文本模式对目标文件进行逐行搜索,显示能被模式所匹配到的行 包含三个命令:grep.egrep(相当于grep -E 扩展的正则表达式)和fgrep(相当于grep ...
- Android之Builder对话框的一些常用方式
原文: http://blog.csdn.net/kkfdsa132/article/details/6322835 Android为我们提供几种对话框,主要有:AlertDialog.Progres ...
- matlab学习 — 实现简单的爬虫
这里复杂的情况暂时不考虑..测试网址为pixiv的每日排行榜 = = url = 'https://www.pixiv.net/ranking.php?mode=daily' text = webre ...
- 什么是Device ID?
Android ID用于唯一识别一部设备的一次刷机行为,虽然不能完全确定该设备的唯一性(真的唯一性是用IMEI号的),但是可以很大程度上过滤重复设备.这是移动互联网广告行业的基础,尤其是CPI广告,设 ...
- webpack配置文件里loader的执行顺序:从下到上,从右到左; css-loader开启css模块化modules: true,
注释: options:{ importLoaders: 2 } 解决样式文件里使用@import 'xxx.xxx' 的问题 module: { rules: [{ test: /\.scss$/, ...
- FLASK - 请求和响应
请求都封装在request对象里面了 from flask import Flask from flask import request from flask import render_templa ...
- 【快学springboot】11.整合redis实现session共享
前言 这里都是基于前面的项目基础上的.springboot整合redis非常的方便,这也是springboot的宗旨,简化配置.这篇文章就教大家如何使用springboot整合redis来实现sess ...
- python表白代码1.0桃心输出
python爱心表达函数初级版本:def my_heart(a,b=2): print("\n".join(["".join([(a[(x-y) % len(a ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表单:复选框(Checkbox)和单选框(Radio)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Intent的常用属性action和category
设置隐式跳转 首先在我们按钮监听器中添加 Intent i=new Intent(); //参数为字符串,可以添加包名.活动名 i.setAction("com.example.aaaaa. ...