第一次成功上分(?
A. Ahahahahahahahaha
这啥鬼名字(
给定个由0,1组成的数列,从中删除不超过n/2的数,令新生成的数列奇数位和偶数位的和相等。
我们知道一个数列要是全是0,或者全是1且长度是偶数,就满足条件了。
所以,先遍历统计1的个数
1.1的个数<=n/2,输出n/2个0就完事
2.1的个数>n/2,输出n/2或者n/2+1个1,令数列长度为偶数
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include<vector>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
int dataa[100000];
int main() {
ll ans = 0;
ll n;
cin >> n;
while (n--)
{
ll k;
cin >> k;
ll sum1 = 0;
for (int i = 0; i < k; i++) {
scanf("%d", &dataa[i]);
sum1 += dataa[i];
}
if (sum1 <= k / 2) {
cout << k / 2 << '
';
for (int i = 0; i < k/2; i++) {
cout << "0 ";
}
}
else {
int cnt;
if (k / 2 & 1)cnt = k / 2 + 1;
else cnt = k / 2;
cout << cnt << '
';
for (int i = 0; i <cnt; i++)cout << "1 ";
}
cout << "
";
}
}
B. Big Vova
贪心就完事
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include<vector>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
int dataa[100000];
int gcd(int a, int b) {
if (b == 0)return a;
gcd(b, a % b);
}
int main() {
ll ans = 0;
ll n;
cin >> n;
while (n--)
{
ll k;
cin >> k;
ll sum1 = 0;
for (int i = 0; i < k; i++) {
scanf("%d", &dataa[i]);
}
sort(dataa, dataa + k);
int ans = 0;
for (int i = 0; i < k; i++) {
int tmp1=0, ansm =-1;
for (int j = 0; j < k; j++) {
if (dataa[j] == -1)continue;
if (gcd(dataa[j], ans) > ansm)tmp1 = j, ansm = gcd(dataa[j], ans);
}
cout << dataa[tmp1] << ' ';
dataa[tmp1] = -1;
ans = ansm;
}
cout << '
';
}
}
C. Chocolate Bunny
以前没写过交互。。。但是居然过了
给定一个1到n的排列,每次可以询问第i个数模第j个数的值,在不超过2*n次询问获得这串排列
我们知道a<b时a%b=a,b%a<a,因此可以询问a%b和b%a获得a的值。因此每2次询问,我们都能得到一个数,进行2*(n-1)次询问,最后遍历一遍确定最后一个数是多少即可。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include<vector>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
int dataa[100000];
int gcd(int a, int b) {
if (b == 0)return a;
gcd(b, a % b);
}
int main() {
ll ans = 0;
ll n;
cin >> n;
memset(dataa, -1, sizeof(dataa));
int l = 1, r = 1;
for (int i = 1; i <n; i++) {
int tmp1, tmp2;
while (dataa[l] != -1)l++;
r = l + 1;
while (dataa[r] != -1)r++;
cout << "? " << l << ' ' << r << '
';
cout.flush();
cin >> tmp1;
cout << "? " << r << ' ' << l << '
';
cout.flush();
cin >> tmp2;
if (tmp1 > tmp2)dataa[l] = tmp1;
else dataa[r] = tmp2;
}
int pos = 0;
for (int i = 1; i <= n; i++) {
ans += dataa[i]; if (dataa[i] == -1) {
pos = i;
ans++;
}
}
dataa[pos] = n*(n+1)/2-ans;
cout << "! ";
for (int i = 1; i <= n; i++) {
cout << dataa[i] << ' ';
}
cout << endl;
cout.flush();
}
D. Discrete Centrifugal Jumps
单调栈/DP
不会(
给定一个h数组,按以下规则(i<j)进行移动,问从h[1]到h[n]最少要多少步
- j=i+1
- max(hi+1,…,hj−1)<min(hi,hj)
- max(hi,hj)<min(hi+1,…,hj−1)
首先考虑DP,状态dp[i]为从第一个点到第i个点需要的最小步数
然后考虑单调栈优化,单调栈可以用于求以某个数为最值的最大区间 参考单调栈&单调队列
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include<vector>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
int n, k;
stack<long long>up,down;
ll dataa[1000000 + 5];
ll dp[1000000 + 5];
int main() {
cin >> n;
for (int i = 0; i < n; i++)scanf("%d",&dataa[i]);
memset(dp, 0x3f, sizeof(dp));
dp[0] = 0;
up.push(0);
down.push(0);
for (int i = 1; i < n; i++) {
dp[i] = dp[i - 1] + 1;
while (!up.empty() && dataa[up.top()] <= dataa[i])
{
ll x = dataa[up.top()];
up.pop();
if(!up.empty()&&x<dataa[i])
dp[i] = min(int(dp[i]), int(dp[up.top()] + 1));
}
up.push(i);
while (!down.empty()&&dataa[down.top()]>=dataa[i])
{
ll x = dataa[down.top()];
down.pop();
if (!down.empty() && x > dataa[i])
dp[i] = min(int(dp[i]), int(dp[down.top()] + 1));
}
down.push(i);
}
cout << dp[n - 1];
}