A. Game
题意:由一个0和1组成的一维数组,起点1和终点n是1,1表示陆地,0表示海洋,可以花费x从 i i i到达 i + x i+x i+x(至多一次),即终点是一定可达的,求最少花费。
思路:讲开头和结尾的连续的1去掉,减一下就是答案。
// Problem: A. Game
// Contest: Codeforces - Codeforces Round #775 (Div. 2, based on Moscow Open Olympiad in Informatics)
// URL: https://codeforces.com/contest/1649/problem/0
// Memory Limit: 256 MB
// Time Limit: 1000 ms#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int mod=1000000007 , N = 1e2 + 10;
const double eps=1e-8;
int t;
int a[N];
int n;
int main(){cin>>t;while(t--){cin>>n;memset(a,0,sizeof a);for(int i = 0 ; i < n ; i ++ ) cin>>a[i];int ans = 0;int j = n-1 , i = 0;while(a[i] && i < n-1) i++;while(a[j] && j > 0) j--;if(j == 0) cout<<"0\n";else{ans = j - i + 2;cout<<ans<<"\n";}}return 0;
}
B. Game of Ball Passing
题意:n个同学在玩传球游戏,给出每个同学的传球次数,问需要最少多少个球来使所有同学的传球结束。
样例1:四个同学分别是:2 3 3 2
可以通过一个球解决: 2 → 1 → 3 → 4 → 1 → 2 → 3 → 4 → 2 → 3 → 2. 2→1→3→4→1→2→3→4→2→3→2. 2→1→3→4→1→2→3→4→2→3→2.
样例2:三个同学分别是:1 5 2
需要两个球解决: 2 → 1 → 2 → 3 → 2 → 1. 2→1→2→3→2→1. 2→1→2→3→2→1.
2 → 3 → 2 → 1 2→3→2→1 2→3→2→1
思路:问题在于解决传球次数最多的同学,经分析后发现只有两种情况
- 最大值大于其余人的和,那么结果就是max-sum
- 否则显然一个球就足够
// Problem: B. Game of Ball Passing
// Contest: Codeforces - Codeforces Round #775 (Div. 2, based on Moscow Open Olympiad in Informatics)
// URL: https://codeforces.com/contest/1649/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int mod=1000000007 , N = 1e5 + 10;
const double eps=1e-8;
int t,n;
int a[N];
int main(){scanf("%d",&t);while(t--){scanf("%d",&n);bool flag = false;ll sum = 0;for(int i = 0 ; i < n ; i ++ ){scanf("%d",&a[i]);sum += a[i];if(a[i]) flag = true;} if(!flag){printf("0\n");continue;}sort(a,a+n);sum -= a[n-1];printf("%lld\n",max((ll)1,a[n-1] - sum));}return 0;}
C. Weird Sum
题意 :给出一个n*m的矩阵,计算值相同的两个点之间的曼哈顿距离(不了解的可以搜一下),对于一对点只计算一次。
思路 :两个点的曼哈顿距离由x,y的差值组成,那么显然可以将x和y两个方向的分开计算,每次将权值相同的点的x和y分别存放排序,然后只每个点和前面的点计算差值,避免重复。
// Problem: A. Weird Sum
// Contest: Codeforces - Codeforces Round #775 (Div. 1, based on Moscow Open Olympiad in Informatics)
// URL: https://codeforces.com/problemset/problem/1648/A
// Memory Limit: 256 MB
// Time Limit: 2000 ms#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<ll,ll> PII;
const int mod=1000000007 , N = 1e5 + 10;
const double eps=1e-8;
vector<PII> ve[N];
ll dis(vector<PII> a,int n)
{vector<ll> l,r;for(int i = 0 ; i < n ; i ++ ){l.push_back(a[i].first);r.push_back(a[i].second);}sort(l.begin(),l.end());sort(r.begin(),r.end());ll sum = 0 , ans1 = 0 , ans2 = 0;for(int i = 0 ; i < n ; i ++ ){ans1 += ((ll)l[i]*i - sum);//每个点避免重复计算,只计算每个点之后的//所以等同计算该点与前面的点的差值,i就是前面有多少点sum += l[i];}sum = 0;for(int i = 0 ; i < n ; i ++ ){ans2 += ((ll)r[i]*i - sum);sum += r[i];}return ans1 + ans2;
}
int main(){int n,m;cin>>n>>m;for(int i = 0 ; i < n ; i ++ ){for(int j = 0 ; j < m ; j ++ ){int x;cin>>x;ve[x].push_back({i,j});}}ll ans = 0;for(int i = 0 ; i <= N - 10 ; i ++ ){vector<PII> a = ve[i];int len = a.size();ans += dis(a,len);}cout<<ans<<"\n";return 0;
}
D. Integral Array
题意:各一个长度为n的数组,数组里面的所有数的值不会大于c, 问是否可以找到两个数x,y(x>=y)都在数组中存在,但是 [ x / y ] [x/y] [x/y] (x除以y向下取整) 在数组中找不到,可以输出No,否则输出Yes。 ( 1 < = n < = 1 e 6 , 1 < = c < = 1 e 6 ) (1<=n<=1e6 , 1<=c<=1e6) (1<=n<=1e6,1<=c<=1e6).
思路:显然暴力的做法不可取,那么可以换个思路,不直接去找x和y,假定x除以y向下取整的数为t,那么可以针对数组中不存在的t,找一个数组中存在的分母y,那么区间 [ y ∗ t , y ( t + 1 ) − 1 ] [y*t,y(t+1)-1] [y∗t,y(t+1)−1]就是x的取值范围,假定数组中存在区间内的数,那么就找到了我们想要的结果。
这里使用一个前缀和数组来直接判断区间内是否有数组中的数存在。
// Problem: B. Integral Array
// Contest: Codeforces - Codeforces Round #775 (Div. 1, based on Moscow Open Olympiad in Informatics)
// URL: https://codeforces.com/contest/1648/problem/B
// Memory Limit: 512 MB
// Time Limit: 2000 ms#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int mod=1000000007 , N = 1e6 + 10;
const double eps=1e-8;
int a[N],st[N*2];
ll s[N*2];
int main(){int t;scanf("%d",&t);while(t--){int n,c;scanf("%d%d",&n,&c);for(int i = 1 ; i <= 2*c ; i ++ ) st[i] = 0;for(int i = 1 ; i <= n ; i ++ ){scanf("%d",&a[i]);st[a[i]] ++;}for(int i = 1 ; i <= 2*c ; i ++ ) s[i] = s[i-1] + st[i];bool flag = true;for(int i = 1 ; i <= c ; i ++ ){ if(!st[i]) continue;for(int j = 1 ; j * i <= c ; j ++ ){if(st[j]) continue;if(s[i*j-1] != s[i*(j+1)-1]) flag = false;//这里区间的右端点最坏取到2*c,所以数组大小开二倍}}if(flag) printf("Yes\n");else printf("No\n");}return 0;
}