当前位置: 首页 > news >正文

AtCoder Beginner Contest 428(ABCDEF)

前言

你管这叫beginner contest???

一、A - Grandma's Footsteps

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;void solve()
{int s,a,b,x;cin>>s>>a>>b>>x;int round=x/(a+b);int sum=round*a*s;int nxt=x%(a+b);if(nxt<a){cout<<sum+s*nxt<<endl;}else{cout<<sum+s*a<<endl;}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

首先因为走a秒歇b秒,所以一轮的总时间就是a+b秒,那么就可以求出一共可以走几轮。同时,走完之后肯定还会剩几秒,那么再特判一下剩的这几秒都在走还是走完了歇一会即可。

二、B - Most Frequent Substrings

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;void solve()
{int n,k;cin>>n>>k;string s;cin>>s;s=" "+s;map<string,int>cnts;for(int i=1;i<=n-k+1;i++){cnts[s.substr(i,k)]++;}int ans=0;for(auto [s,c]:cnts){ans=max(ans,c);}cout<<ans<<endl;for(auto [s,c]:cnts){if(c==ans){cout<<s<<" ";}}cout<<endl;
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

这个题直接暴力即可,建立一个滑动窗口,把所有长度为k的子串都收集起来,然后先找出最大词频,然后再把这个词频对应的子串全输出即可。

三、C - Brackets Stack Query

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;void solve()
{int q;cin>>q;vector<int>sum={0};int low=0;int op;char ch;while(q--){cin>>op;if(op==1){cin>>ch;if(ch=='('){sum.push_back(sum.back()+1);}else{sum.push_back(sum.back()-1);if(low==0&&sum.back()<0){low=sum.size();}}}else{sum.pop_back();if(sum.size()<low){low=0;}}if(low==0&&sum.back()==0){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

这个题就涉及到括号匹配的知识了。首先,对于能匹配的括号串,将左括号看作+1,右括号看作-1。那么若一个括号串能匹配,就说明按上述方式所求累加和等于0,且中间每一个位置的前缀和都大于等于0。所以考虑用一个sum数组存每一个位置的前缀和,再用一个low变量记录第一个前缀和小于0的位置。那么对于每一个右括号,都判断一下若low没有设置且当前的前缀和小于0了,就把low设置成当前sum数组的长度。那么之后每次删末尾就是让sum数组pop_back一下,然后若长度小于low了,就说明此时每个位置又满足了前缀和大于等于0,所以把low设为0。所以最后只需要判断一个sum数组的最后一位是否是0且low是否是0即可。

四、D - 183184

讨厌数学题……

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;//求1~x范围上的平方数的个数
//sqrt会有精度问题
ll cal(ll x)
{ll res=sqrt(x);//手动修正while(res*res>x){res--;}while((res+1)*(res+1)<=x){res++;}return res;
}void solve()
{ll c,d;cin>>c>>d;//若C+x有d位,那么拼接的结果就是C*10^d+C+x//所以可以考虑去枚举C+x的位数d,有10^(d-1)<=C+x<=10^d-1//整理得10^(d-1)-C<=x<=10^d-C-1//又因为1<=x<=D,所以可以有左边界L=max(1,10^(d-1)-C),右边界R=min(D,10^d-C-1)//又因为f(C,C+x)=C*10^d+C+x,就有C*10^d+C+L<=f(C,C+x)<=C*10^d+C+R//所以就转化成了求这个区间内有多少个平方数ll ans=0;//i:当前是10的i次方//j:10的i次方for(ll i=1,j=10;i<=10;i++,j*=10){ll L=max(1ll,j/10-c);ll R=min(d,j-c-1);if(L>R){continue;}ans+=cal(j*c+c+R)-cal(j*c+c+L-1); }cout<<ans<<endl;
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;cin>>t;while(t--){solve();    }return 0;
}

首先观察到若C+x有d位,那么拼接后的结果就是C*10的d次方+C+x,所以可以考虑去枚举C+x的位数d。那么就有10的d-1次方小于等于C+x小于等于10的d次方-1,,所以移项后就有10的d-1次方-C小于等于x小于等于10的d次方-1-C。又因为1<=x<=D,所以左边界L就等于10的d-1次方-C和1的最小值,右边界R就等于10的d次方-1-C和D的最小值。又因为f(C,C+x)等于C*10的d次方+C+x,所以就有C*10的d次方+C+L小于等于f(C,C+x)小于等于C*10的d次方+C+R,那么问题就转化成了求这个区间内有多少个平方数。

注意sqrt面对long long会有精度问题,所以要手动修正一下。

五、E - Farthest Vertex

byd马上要看左老师树的直径这一节,结果正好考了这么一个题,哪里不会考哪里了属于是……

先空着,我看完课立马补!()

六、F - Pyramid Alignment

你已经学会了二分,快来做做F吧!(疯)

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;const int MAXN=2e5+5;vector<ll>a(MAXN);//连续段组
vector<array<ll,4>>seg;//返回v这个线段当前的左右端点
pll query(array<ll,4>&cur,ll v)
{if(cur[3]==0){return {cur[2],cur[2]+a[v]};}else{return {cur[2]-a[v],cur[2]};}
}//二分搜索编号为v的区间的左右端点
pll find(ll v)
{int l=0;int r=seg.size()-1;int m;int ans=-1;while(l<=r){m=l+r>>1;if(seg[m][1]>=v){ans=m;l=m+1;}else{r=m-1;}}return query(seg[ans],v);
}//二分搜索编号为v的区间所在的连续段
int findSeg(ll v)
{int l=0;int r=seg.size()-1;int m;int ans=-1;while(l<=r){m=l+r>>1;//当前连续段编号最大的区间的左右端点auto cur=query(seg[m],seg[m][1]);//全包 -> 左闭右开if(cur.first<=v&&v<cur.second){ans=m;l=m+1;}else{r=m-1;}}return ans;
}//在v所在连续段中二分搜索最小包含v的区间
int findV(int l,int r,int pos,ll v)
{int m;int ans=-1;while(l<=r){m=l+r>>1;auto cur=query(seg[pos],m);//全包 -> 左闭右开if(cur.first<=v&&v<cur.second){ans=m;r=m-1;}   else{l=m+1;}}return ans;
}void solve()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}//不管是操作1还是操作2,每次都会生成一个左端点或右端点相同的连续段,所以考虑以这个连续段为单位维护线段//定义四元组(l,r,x,t)为编号区间[l,r]中的所有端点的(t==0?左:右)端点全部移动到了x,然后对其按r从小到大排序//对于操作1和2,每次操作时,可以二分搜索v所在的连续段,找出连续段的L和R//之后从小到大遍历,暴力考虑所有连续段u//若Ru<=v,那么直接删除这个连续段,否则就替换Lu=v+1,插入(1,v,Lv/Rv,0/1),结束遍历//由于至多插入q次,所以删除也至多q次,所以均摊下来只会修改O(q)次连续段//对于操作三,因为无论如何操作,大的区间必然包含了小的区间//所以只需要找到第一个包含x+1/2的线段p,答案为n-p+1//那么就是第一次二分找出该连续段,第二次二分在该连续段内二分//整体时间复杂度O(nlogn)//vector方便在末尾push和pop,所以倒序存入for(int i=n;i>=1;i--){seg.push_back({i,i,a[i],1});}int q;cin>>q;int op,v;while(q--){cin>>op>>v;if(op<=2){auto info=find(v);while(!seg.empty()){auto last=seg.size()-1;if(seg[last][1]<=v){seg.pop_back();}else{seg[last][0]=v+1;break;}}if(op==1){seg.push_back({1,v,info.first,0});}else{seg.push_back({1,v,info.second,1});}}else{int pos=findSeg(v);   if(pos==-1){cout<<0<<endl;continue;}pos=findV(seg[pos][0],seg[pos][1],pos,v);if(pos==-1){cout<<0<<endl;continue;}cout<<n-pos+1<<endl;}}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

这题补的时候真的一眼二分,但想了半天没想出来怎么二分,没想到题解居然这么复杂……

首先,不管是操作1还是操作2,每次都会生成一个左端点或右端点相同的连续段,所以考虑以这个连续段为单位维护每个线段。所以考虑定义一个四元组(l,r,x,t),表示编号从l到r的线段,当前(t==0?左:右)端点都在x处,然后对其按r从小到大排序。之后,不管对于操作1还是操作2,每次操作时,可以二分搜索v所在的连续段,找出v这个线段当前的L和R。之后就可以暴力从小到大遍历每个连续段,若当前连续段的r小于v,那么就可以直接删除,否则就替换当前连续段的l为v+1,然后插入(1,v,L/R,0/1)。而对于操作3,因为注意到无论如何操作,大的区间一定包含了小的区间,所以只需要找到包含x+1/2的最小区间即可,所以可以考虑第一次二分找出x+1/2所在的连续段,再在这个连续段内二分找出最小区间即可。

总结

我感觉这套题放div2都够了……

END

http://www.dtcms.com/a/525775.html

相关文章:

  • Mysql杂志(三十五)——Bin log
  • 建设网站外包公司苏州网站建设品牌
  • 能注册账号的网站模板开发板哪个好
  • 网站建设如何赚钱琴行网站开发学术论文
  • 年份与季度筛选组件封装
  • KingbaseES数据库:异构多活构建极致容灾
  • 做网站一个人能做吗网页设计六安模板
  • 河南郑州做网站的公司wordpress图片切换插件
  • 方法重写111
  • Spring依赖管理核心技巧与应用
  • java面试:有了解过消息队列mq吗,详细讲解一下
  • 建设校园网站公司怎么介绍自己的优势
  • 第十四届蓝桥杯大赛软件赛国赛Java大学C组(部分)
  • 2025年--Lc211- 557. 反转字符串中的单词 III--Java版
  • 网站建设售后服务承诺网站做多久才有流量
  • 网站外包制作工程建设报道
  • 【u-boot】u-boot启动文件start.S剖析(ARM64)
  • 【JUnit实战3_11】第六章:关于测试的质量(下)
  • 最新选题-基于Spark的二氧化碳排放量数据分析系统设计
  • 438.找到字符串中所有字母异位词
  • 鞍山手机网站设计广东省室内设计公司排名
  • 适合seo优化的网站制作网站鼠标特效
  • 【无标题】叽叽喳喳
  • 多线程六脉神剑第四剑:读写锁 (ReaderWriterLockSlim)
  • 网站设关键字wordpress搭建问答系统
  • 泉州高端网站建设微信h5免费制作网站模板下载
  • 第13章-人员管理
  • Maya Python入门:属性连接connectAttr()、创建节点createNode()
  • Java学习之旅第三季-17:Lambda表达式
  • 企业电子商务网站建设和一般建设网站收费标准