$CF 633 (Div 2)$

(CF 633 (Div2))

(A.)

水题

竖着的菱形决定了横着的菱形,所以答案即为竖着的菱形个数,即 (n)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 1e6 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
 
 
inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}
 
int main()
{
    int t;
    scanf("%d", &t);
    while(t--) {
        int n; scanf("%d", &n);
        printf("%d
", n);
    }
    return 0;
}

(B.)

先排序,然后首尾取,即可构造答案,最后倒序输出即可

正确性证明:

设头为 (i),尾为 (j),倒数第二个为 (k)

满足 (ileq kleq j)

所以 (j - igeq k - i)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 1e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;

inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}

int t, n, cnt, a[N], ans[N];
int main()
{
    scanf("%d", &t);
    while(t--) {
        memset(ans, 0, sizeof(ans));
        cnt = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) a[i] = read();
        sort(a + 1, a + 1 + n);
        int x = n, y = 1;
        while(cnt < n)
            ans[++cnt] = a[x--], ans[++cnt] = a[y++];
        for(int i = n; i >= 1; --i)
            printf("%d%c", ans[i], " 
"[i == 1]);
    }
    return 0;
}

(C.)

对于每对 (i, j, i < j), 若 (a[i] > a[j]),那么 (a[j]) 必须通过增值来越过 (a[i])

设时间为 (t),则增长的最大值为 (2^{t} - 1)

那么 (t = leftlceil log2(a[i] - a[j] + 1) ight ceil)

若存在 (k) 介于 (i, j) 之间

  • (a[k]leq a[j]),那么 (a[k], a[j]) 一同增值越过 (a[i]),仍然保证了 (a[k], a[j]) 的相对大小
  • (a[k] > a[j]),那么让 (a[k]) 某些时刻不增值,(a[j]) 增值即可

遍历答案,找到最大的 (a[i] - a[j], i < j),算出对应的 (t) 即可

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 1e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;


inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}

int t, n;
int main()
{
    t = read();
    while(t--) {
        n = read();
        int x = -inf, ans = 0;
        for(int i = 1; i <= n; ++i) {
            x = max(x, a[i]);
            ans = max(ans, x - a[i]);
        }
        ans = ceil(log2(ans + 1));
        printf("%d
", ans);
    }
    return 0;
}

比赛时纠结的一个点是

(a[k] > a[j]),是否能保证增值后满足 (a[k]leq a[j])

事实上这是可以保证的,因为 (a[j]) 为了越过 (a[i]),最大增值可以是 (2^{t} - 1)

不管 (a[k])(a[j]) 大多少,都可以先让 (a[j]) 追上 (a[k]),然后一起增值超过 (a[i])

原文地址:https://www.cnblogs.com/ChenyangXu/p/12693013.html