第一周周报
这一周是寒假训练的第一周,训练内容主要就是做牛客上的题单还有比赛,牛客上的题单还是比较痛苦的,因为牛客压根看不了测试用例,导致我事后想知道错的例子是什么都看不了。做第一题第二题还有倒数第三题有一两个例子一直都过不去。检查了很久的代码,一直是差一两个例子,就老是想用自己代码思路去解决问题,就卡很久。
个人训练就是巩固了二维数组,dfs和差分算法,对三个算法的理解和应用又加深了一些。之后寒假的时间就准备对每个算法分别都进行加深理解,还是有很大的进步空间的,希望在以后竞赛取得更好成绩。
写了一些我觉得有意思的题的题解
题单1.数学考试,正解使用到离散化和前缀和,我的方法相对来说比正解要简单一点,
用了前缀和算法了两次,比较巧妙的来计算分数的最大值。第一次前缀是来计算分数,第二次前缀是截取一部分的分数总和。
include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
long long n,k,num[2000005]={0},ans=-1e18,ss[2000006]={0};
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++){
cin>>num[i];
num[i]+=num[i-1];
}
for(int i=1;i<=n;i++){
if(i-k>=0)
ss[i]=num[i]-num[i-k];
}
num[n]=ss[n];
for(int i=n-1;i>=1;i--)
num[i]=max(ss[i],num[i+1]);
for(int i=k;i<=n;i++)
ans=max(ans,ss[i]+num[i+k]);
printf("%lld\n",ans);
}
}
题单I值周
这个就是用到了差分,与简单版本比较差别就是数据范围要更大了点。跟CF上面的一道题比较像。我是用结构体数组来存储数字,一个存储值,一个来存1或-1.再用快排进行排序,遍历一遍来求的结果
include<bits/stdc++.h>
//#define int long long;
using namespace std;
struct pe{
long long a,b;
}st[2000006];
bool compare(struct pe q,struct pe w){
if(q.a!=w.a)
return q.a<w.a;
else
return q.b>w.b;
}
signed main(){
long long n,m;
scanf("%lld%lld",&n,&m);
long long y=1;
for(int i=1;i<=m;i++){
long long a,b;
scanf("%d%d",&a,&b);
st[y].a=a;
st[y].b=-1;
st[y+1].a=b;
st[y+1].b=1;
y+=2;
}
sort(st+1,st+2m+1,compare);
long long ans=st[1].a,num=-1;
for(long long i=2;i<=2m-1;i++){
if(num==0){
ans+=st[i].a-st[i-1].a-1;
}
num+=st[i].b;
}
ans+=n-st[2m].a;
printf("%d",ans);
return 0;
}
PTA7-14寻宝图
这一题其实就是深搜,自己也第一时间想到了这一算法,但是提交过程中发现内存会爆,用来标记的vis数组满足不了数据范围,当时冥思苦想了很久也没有解决,例子最后一个没有通过。
补题时想到利用字符串数组来存储,并且还是利用字符串来标记走过的路程,只需要把走过的点设为‘’,来达到标记的作用。
include<bits/stdc++.h>
using namespace std;
string s[100005];
int X[5]={0,-1,0,1,0},Y[5]={0,0,1,0,-1},vis[9999][9999];
int ans,num,n,m,ju;
void dfs(int x,int y){
if(s[x][y]>='2'&&ju==0)
num++,ju=1;
s[x][y]='';
for(int i=1;i<=4;i++){
int x1=x+X[i],y1=y+Y[i];
if(x1>=0&&x1<n&&y1>=0&&y1<m&&s[x1][y1]!='0'&&s[x1][y1]!='')
dfs(x1,y1);
}
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>s[i];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]!='0'&&s[i][j]!='*'){
ju=0;
dfs(i,j);
ans++;
}
}
}
cout<<ans<<' '<<num;
}
PTA 拯救007;
这一题当时做的时候知道使用dfs,但是想了很久感觉到无从下手,赛后补题时看了正解,慢慢有了思路。
把007跳过的过程分为三部分,分别用三个函数来实现.第一个是判断是否能到岸上,因为有四个方向所以if判断语句中有四个条件。第二个函数是第一步跳的位置来用一个函数判断。
第三个函数就是dfs函数,不断搜索并调用其他函数实现过程。真的是要把功能分块实现更加条理清晰。
include<bits/stdc++.h>
using namespace std;
struct node
{
int x,y;
}p[110];
int vis[110];
int flag = 0;
int n,m;
int keyi(int x)//如果可以成功到达岸边
{
if((p[x].x - m<=-50)||(p[x].x + m>=50)||(p[x].y - m<=-50)||(p[x].y + m >=50))
return 1;
return 0;
}
int first(int x)//第一步
{
int p1 = pow(p[x].x,2);
int p2 = pow(p[x].y,2);
int r = (m+7.5)(m+7.5);
if(p1+p2<=r)
return 1;
return 0;
}
int jump(int x,int y)//能否从一个鳄鱼头跳到另一个鳄鱼头
{
int p1 = pow(p[x].x - p[y].x,2);
int p2 = pow(p[x].y - p[y].y,2);
int r = mm;
if(p1+p2<=r)
return 1;
return 0;
}
int dfs(int t)
{
vis[t] = 1;
if(keyi(t) == 1)
{
flag = 1;
}
for(int i=0;i<n;i++)
{
if(!vis[i]&&jump(t,i))
{
flag = dfs(i);
// if(flag == 1)
// break;
}
}
return flag;
}
int main()
{
memset(vis,0,sizeof(vis));
scanf("%d %d",&n,&m);
int i;
for(i=0;i<n;i++)
{
scanf("%d %d",&p[i].x,&p[i].y);
}
if(m>=42.5)
{
printf("Yes\n");
}
else
{
for(i=0;i<n;i++)
{
if(!vis[i]&&first(i))
{
dfs(i);
}
}
if(flag == 1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
这一周比赛还是有收获的,对我有收获的题写了题解,其他的好多都考虑的不够周全一直wa,还有一部分题,算法还没有学到就没有补了。
希望接下来收获更大,继续努力!!!