Codeforces Round #669 Div. 2

第一次成功上分(?

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 << '\n';
		      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 << '\n';
		      for (int i = 0; i <cnt; i++)cout << "1 ";
	      }
	      cout << "\n";

      }
  }

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 << '\n';
      }
  }

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 << '\n';
	      cout.flush();
	      cin >> tmp1;
	      cout << "? " << r << ' ' << l << '\n';
	      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];
}
posted @ 2020-09-09 21:21  PopHirasawa  阅读(158)  评论(0编辑  收藏  举报