Codeforces Round #831 (Div. 1 + Div. 2)

C

核心思路:这个题目其实是一个规律题,它有一个很重要的前提,那就是在分配方案最优的情况下,要不然我们直接选几个差值最大的就ok,那他这句话,其实我们结合几个样例就知道,有一个必须得是紧挨另外一个的,也就是次大值。

所以我们可以先排好序,然后我们从前往后遍历下,在从后往前。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 10e9 + 7;
const int N = 1e7;
int primes[N], st[N], cnt;

void solve()
{

}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		ll n;
		cin >> n;
		vector<ll> a;
		for (int i = 0;i < n;i++)
		{
			int x;
			cin >> x;
			a.push_back(x);
		}
		sort(a.begin(), a.end());
		ll ans = 0;
		for (int i = 0;i < n - 2;i++)
		{
			ans = max(ans, a[i + 1] - a[i] + a[n - 1] - a[i]);
		}
		for (int i = n - 1;i >1;i--)
			ans = max(ans, a[i] - a[i - 1] + a[i] - a[0]);
		cout << ans << endl;
	}
}

D

核心思路:这个我们要读懂题意。然后模拟下就会发现只要我们有两个空位那么就肯定可以将棋子移动到指定位置,也就是我们整个棋盘的最大承载容量是n*m-4,因为(1,1)和(n,m)是已经固定了,如果要大于(不可以取等号)这个最大容量肯定就不可以。然后我们可以使用树状数组来维护这个棋子数目前缀和。

其实为什么可以使用这个我们可以注意a[i]的值正好对应\(1\sim n\),所以我们需要注意我们使用树状数组时,区间需要连续.不连续可以用离散化是其连续

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
ll n,m,k;
int a[N], ans[N], tr[N];
int lowbit(int x)
{
    return x & -x;
}
int ask(int x)
{
    int res = 0;
    for (int i = x;i;i -= lowbit(i))
        res += tr[i];
    return res;
}
void add(int x, int v)
{
    for (int i = x;i <= k;i += lowbit(i))//一定要注意这个地方是小于k,不要把模板背得太死了。这个是小于我们的数组容量.
        tr[i] += v;
}
void solve()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= k; i++) cin >> a[i], tr[i] = 0;
    bool flag = true;
    for (int i = 1; i <= k; i++) {
        if (ask(a[i]) >= n * m - 3) flag = false;
        add(a[i], 1);
    }
    if (flag) cout << "YA" << endl;
    else cout << "TIDAK" << endl;
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
}
posted @ 2022-11-23 16:22  努力的德华  阅读(29)  评论(0)    收藏  举报