1649A Game
- 题目大意
一个长度为n的01序列,从坐标1跳到坐标n的最小花费:只能在1上行走,在相邻的1之间跳跃不花费,从坐标i跳到坐标i+x花费x。 - 思路
找到最左边和最右边的连续1。 - code
#include<bits/stdc++.h>
using namespace std;
int t,n,x,a[110];
int main()
{
cin>>t;
while(t--)
{
scanf("%d",&n);
int ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int i=n;
while(a[i-1]==1 && i-1>=1)
{
i--;
}
int j=1;
while(a[j+1]==1 && j+1<=n)
{
j++;
}
if(i==1) printf("0\n");
else printf("%d\n",i-j);
}
return 0;
}
1649B Game of Ball Passing
- 题目大意
有n个球员,他们之间在互相传球,给出他们每个人传了多少个球a[i],问场上至少要多少个球吃才能满足这个序列。 - 思路
当max(a[i])<=剩余a[i]的和+1,一个球就可以满足;
当max(a[i])>剩余a[i]的和+1,第一个球可以抵消掉max(a[i])中的sum(a[i])+1个,剩下的需要更多的球来满足,并且们每增加一个球就可以抵消一个max(a[i]),故还需要max(a[i])-(sum(a[i])+1)个球。 - code
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
long long t,n,a[N];
int main()
{
cin>>t;
while(t--)
{
scanf("%d",&n);
long long all_zero=1,maxn=0,sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
maxn=max(a[i],maxn);
sum+=a[i];
if(a[i]!=0) all_zero=0;
}
sum-=maxn;
if(all_zero) printf("0\n");
else if(maxn<=sum+1) printf("1\n");
else printf("%lld\n",maxn-sum);
}
return 0;
}
ACWing机试题 836. 合并集合
-
题目大意
并查集裸体 -
思路
-
code
#include<bits/stdc++.h>
using namespace std;
#define N 100010
int n,m,fa[N];
int find(int x)
{
if(fa[x]!=x)
{
return fa[x]=find(fa[x]);
}
else return x;
}
void merg(int x,int y)
{
int fx=find(fa[x]);
int fy=find(fa[y]);
if(fx!=fy)
{
fa[x]=fy;
}
}
int main()
{
cin>>n>>m;
char a;
int b,c;
for(int i=1;i<=n;i++) fa[i]=i;
while(m--)
{
cin>>a>>b>>c;
if(a=='M')
{
merg(find(b),find(c));
}
else
{
if(find(b)==find(c)) cout<<"Yes\n";
else cout<<"No\n";
}
}
return 0;
}
题解是一个带有r标记的代码
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void merge(int a, int b)
{
a = find(a), b = find(b);
if (a == b) return;
if (r[a] > r[b]) p[b] = a;
else
{
p[a] = b;
if (r[a] == r[b]) r[b] ++ ;
}
}