Codeforces Round #763 (A-C)
Codeforces Round #763 (A-C)
A. Robot Cleaner
题意:
给一个\(n\times m\)的方格,起点为\(x1 ,y1\) 目标垃圾在\(x2,y2\) ,从起点开始每次移动对应\(x,y\)方向上同时加1,如果碰到边界则该方向加值取反。每次移动都可以扫除该行,列上所有的垃圾。问目标垃圾在第几次移动时被扫除
思路:
一开始写的时候,加载图片卡了好久。看完图片读题后发现数据量很小,直接暴力模拟
#include<bits/stdc++.h>
#include<set>
#include<deque>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>PII;
const int N = 2e5+10,inf = 0x3f3f3f3f;
int a[110][110];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int n,m,sx,sy,ex,ey;
cin >> n >> m >> sx>>sy>>ex>>ey;
if(sx == ex || sy == ey) cout << 0 <<endl;
else{
int dx = 1 , dy = 1;
int ans = 0;
while(1){
if(sx + dx > n || sx + dx < 1){
dx = -dx;
}
if(sy + dy > m || sy + dy < 1){
dy = -dy;
}
sx += dx;
sy += dy;
ans ++;
if(sx == ex || sy == ey) {
cout << ans <<endl;
break;
};
}
}
}
return 0;
}
B. Game on Ranges
题意:
选手A每次可以在集合\([1-n]\)之间选择一个区间\([l-r]\),然后选手B在\([l-r]\)中选择一个数\(x\),
然后A就把\(x\)从\([l-r]\)中取出。重复这个过程直到整个集合为空,保证n次结束游戏。我们的目标是通过A选手每次给出的区间\([l-r]\)推算出B选择的数\(x\)。
思路:
每次选择的数肯定不一样。
当区间差越小的时候,选择的数的确定的性越高,当\(l=r\)时,选择的数是确定的。
我们对每次的区间差值排序,将确定的数记录并排除,即可保证每个区间有着对应答案
#include<bits/stdc++.h>
#include<set>
#include<deque>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>PII;
const int N = 2e5+10,inf = 0x3f3f3f3f;
struct node{
int l ;
int r ;
int ca;
int id;
}f[1010];
int nums[1010];
int ans[1010];
bool cmp1(node a , node b){
if(a.ca == b.ca) return a.id < b.id;
return a.ca <b.ca;
}
bool cmp2(node a , node b){
return a.id < b.id;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int n;
cin >> n;
for(int i = 1; i <= n; i++) ans[i] = 0, nums[i] = 0;
for(int i = 1; i <= n ; i ++){
cin >> f[i].l >> f[i].r;
f[i].id = i;
f[i].ca = f[i].r - f[i].l;
}
sort(f+1,f+n+1,cmp1);
for(int i = 1; i <= n; i++){
for(int j = f[i].l; j <= f[i].r ; j++){
if(!nums[j]) {
ans[f[i].id] = j;
nums[j] = 1;
}
}
}
sort(f+1,f+n+1,cmp2);
for(int i = 1; i <= n; i++){
cout <<f[i].l <<" " <<f[i].r <<" "<< ans[i] <<endl;
}
cout <<endl;
}
return 0;
}
C. Balanced Stone Heaps
题意:
有着\(n\)堆石子,每堆石子有\(a_i\)个。我们可以有个操作:
通过从第\(3\)堆开始到第\(n\)堆,对于当前我们选择的这堆石子,我们可以选择一个数\(d(0 <= 3\times d <= a_i)\) ,然后让 \(a_{i-1}+d,a_{i-2}+2d\)。
问,通过该操作后n堆石子中,最少的那一堆石子的最大值是多少。
思路:
看见了最小的最大值,就直接开始往二分答案方向进行思考。
二分相当于把答案代进原序列看能否成立,所以我们每次二分前都要存储一遍原序列。
判断是否成立时,原操作是从前往后,但如果模拟这个操作就会进行重复多次判断,所以我们就直接从后往前判断并模拟,当前这个值只会为他的前面两堆做出贡献。最后再检查一遍整个序列是否满足。
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_bcak
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pe;
const int N = 2e5 + 5;
const int INF = 0x3f3f3f3f;
ll a[N], b[N];
int n;
bool check(ll mid){
for(int i = n; i >= 3; -- i){
if(a[i] < mid) return false;
int te = a[i] - mid;
if(te >= b[i]) te = b[i];
te /= 3;
a[i - 1] += te;
a[i - 2] += te * 2;
}
for(int i = 1; i <= n; ++ i) if(a[i] < mid) return false;
return true;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t -- ){
cin >> n;
for(int i = 1; i <= n; ++ i) cin >> b[i];
ll l = 0, r = INF;
ll ans = 0;
while(l <= r){
ll mid = l + r >> 1;
for(int i = 1; i <= n; ++ i) a[i] = b[i];
if(check(mid)){
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
cout << ans << endl;
check(7);
}
return 0;
}

浙公网安备 33010602011771号