Codeforces Round #756(div3) (A-D、F题解)
A:Make Even
签到
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#define ll long long
#define ld long double
#define int long long
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define _rep(i, a, b) for(int i = a; i >= b; i --)
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e6 + 5;
int n, a;
signed main(){
cin >> n;
while(n --){
cin >> a;
if(a % 2 == 0){
cout << 0 <<endl;
continue;
}
int flag = 0;
while(a >= 10){
if(a % 2 == 0)
flag = 1;
a /= 10;
}
if(a % 2 == 0){
cout << 1 << endl;
continue;
}
if(flag){
cout << 2 << endl;
continue;
}
cout << -1 << endl;
}
return 0;
}
B: Team Composition: Programmers and Mathematicians
签到
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#define ll long long
#define ld long double
#define int long long
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define _rep(i, a, b) for(int i = a; i >= b; i --)
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e6 + 5;
int n, a, b, ans;
signed main(){
cin >> n;
while(n --){
cin >> a >> b;
ans = (a + b) / 4;
int t = min(a,b);
ans = min(ans, t);
cout << ans << endl;
}
return 0;
}
C: Polycarp Recovers the Permutation
题目大意:对于一个数组a,选择它的最左或最右的最小值,加到b数组的最左或最右端。现给你b数组,求原来的a数组,如果无法构建出来输出-1。
思路:-1的情况很容易想到,就是整个数组最大值不在两端,剩下的直接模拟就行了。赛后又想了想,直接反转就行了。。。思维还是不行hhh。
代码:
//模拟:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#define ld long double
#define int long long
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define _rep(i, a, b) for(int i = a; i >= b; i --)
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 5;
int a[N], ans[N*2];
int n, t;
signed main(){
cin >> t;
while(t --){
cin >> n;
int m = 0;
for(int i = 0; i < n; i ++)
cin >> a[i], m = max(m, a[i]);
int mx = max(a[0], a[n - 1]);
if(m != mx){
cout << -1 << endl;
continue;
}
int idl = n, idr = n + 1, l = 0, r = n - 1;
while(l < r){
if(a[l] <= a[r])
ans[idl--] = a[l++];
else
ans[idr++] = a[r--];
}
for(int i = idl + 1; i < idr; i++)
cout << ans[i] << " ";
cout << a[l] << endl;
}
return 0;
}
//规律:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#define ld long double
#define int long long
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define _rep(i, a, b) for(int i = a; i >= b; i --)
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 5;
int a[N], ans[N*2];
int n, t;
signed main(){
cin >> t;
while(t --){
cin >> n;
int m = 0;
for(int i = 0; i < n; i ++)
cin >> a[i], m = max(m, a[i]);
int mx = max(a[0], a[n - 1]);
if(m != mx){
cout << -1 << endl;
continue;
}
if(a[0] == mx){
for(int i = n - 1; i > 0; i--)
cout << a[i] << " ";
cout << mx << endl;
}
else{
for(int i = n - 2; i >= 0; i --)
cout << a[i] << " ";
cout << mx <<endl;
}
}
return 0;
}
D: Weights Assignment For Tree Edges
题目大意:给你两个数组a,p,a数组a[i]指i的父亲节点是a[i],当i跟a[i]相等的时候,i就是根节点,而对于每个点到根节点都有一个距离,这些距离关系的排序就是p数组,让你构造出一组点到根节点的距离,满足ap两个数组。
思路:对于每个节点加上一个rank值,再根据p数组来遍历赋值,使得p[i]节点到根节点的距离就是i,子节点自然只需要用i-父亲节点的rank值即可,-1的情况就是父亲的rank值比儿子的tank值更大。题目读懂了思路自然就出来了这道题就很简单了。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#define ll long long
#define ld long double
#define int long long
#define rep(i, a, b) for(int i = a; i < b; i++)
#define _rep(i, a, b) for(int i = a; i >=b; i --)
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 200005;
int a[N], p[N], ans[N], r[N];
int n, t, f;
signed main(){
cin >> t;
while(t --){
bool ok = true;
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> a[i];
if(a[i] == i)
f = i;
}
for(int i = 1; i <= n; i ++) cin >> p[i];
if(p[1] != f)
ok = false;
for(int i = 1; i <= n; i ++)
r[p[i]] = i;
ans[f] = 0;
for(int i = 2; i <= n && ok; i ++)
if(i < r[a[p[i]]])
ok = false;
else
ans[p[i]] = i - r[a[p[i]]];
if(ok == false)
{
cout << -1 << endl;
continue;
}
for(int i = 1; i <= n; i ++)
cout << ans[i] << " ";
cout <<endl;
}
return 0;
}
F: ATM and Students
题目大意:给你一个长度为n的数组以及一个缓冲值s,求其最长的单调区间+s严格非负,若有输出左右端,若无输出-1。(严格单调是指这个区间从l开始,一直到r和都是非负才行,所以前缀和可能行不通)。
思路:双指针直接找最大区间即可(权值线段树的做法应该也可以过,没试过只有个想法)。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#define ld long double
#define int long long
#define rep(i, a, b) for(int i = a; i < b; i++)
#define _rep(i, a, b) for(int i = a; i >=b; i --)
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 5;
int n, t, s;
int a[N];
signed main(){
cin >> t;
while(t --){
cin >> n >> s;
for(int i = 0; i < n; i ++)
cin >> a[i];
int l = 0, r = 0, sum = 0, ans = 0, ll, rr, cnt = 0, mx = 0;
while(r < n && l < n){
if(sum + s + a[r] >= 0) sum += a[r], r++, cnt++;
else if(sum + s + a[r] <= 0 && l == r)l++, r++;
else{
sum -= a[l];
l++;
cnt--;
}
if(mx < cnt){
mx = cnt;
ll = l;
rr = r;
}
}
if(mx)
cout << ll + 1 << " " << rr <<endl;
else
puts("-1");
}
return 0;
}