CodeForces-Array Optimization by Deque暨洛谷最后一篇题解

题目

这个贪心好想 不过证明有点费劲

以后博客不会在洛谷写了 转园了 这是最后一篇了 拿这个当作收尾吧

思路

是一个贪心的思路,对于一个数在入队列时候,放前还是后是一个问题,这个时候我们就要知道队内有多少个元素小于它大于它,然后决定前后顺序,于是我们可以想到把它放进集合里,然后二分查找出来,不过由于是迭代器,不是真实的地址,使用 \(distance\) 函数对于stl是Olen的 数组没必要用这个 所以这边考虑使用orderset 就行了

这个贪心的为什么是对的 其实对于入队的元素和它后面的那个人 其实二者产生的贡献最多是1可能是0 但归根结底 放哪里跟这个二者前后顺序没关系 总不能因为一个1的贡献而不考虑整体吧

#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<int,null_type,less_equal<int>,rb_tree_tag,tree_order_statistics_node_update>
#define endl '\n'
#define int long long 
const int range = 2e5 + 10;
int a[range];int n;
void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i];
	int num = 0;
	ordered_set s;
	s.insert(a[1]);
	unordered_map<int,int>ma;
	ma[a[1]]++;
	for (int i = 2; i <= n; i++) {
		int d = s.order_of_key(a[i]);
		int qian, hou;
		qian = d;
		hou = i-1-ma[a[i]]-d;
		if (qian > hou)num += hou;
		else num += qian;
		s.insert(a[i]);
		ma[a[i]]++;
	}
	cout << num << endl;
}
signed main() {
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--)
		solve();
	return 0;
}

下面给出刚开始写的做法

    auto d = lower_bound(s.begin(), s.end(), a[i]);
    别这样写 会完蛋的 要写S.lowerbound!
		//比多少人大
		int dis;
		if (d != s.end()) {
				dis = distance(s.begin(), d);
		} else dis = i - 1;

坏在distance上面 太耗费时间了

不过用order就行
给出distance使用例子

#include <iostream>
#include <set>
#include <iterator> 

int main() {
	multiset<int> s = {10, 20, 30, 40, 50, 50, 60};
	int a[4] = {10, 25, 50, 70};
	for (int i = 0; i < n; ++i) {
		auto it = lower_bound(s.begin(), s.end(), a[i]);	//懒得改了S.lowerbound
		if (it != s.end()) {
			auto d = distance(s.begin(), it);
			cout  << a[i] << d <<endl;
		} else {
			cout << a[i] <<  endl;
		}
	}
	return 0;
}
 10  position 0
 25  position 2
 50  position 4
 70 没有找到

下面给出orderset的使用例子

set有的他也有 不过他支持了两个成员函数

order_of_key 和 find_by_order这两个好用

order_of_key(k):
返回集合中严格小于 k 的元素个数。

find_by_order(k):

返回集合中第 k 小的元素(0-indexed)。

假设有

1 2 3 4

os.order_of_key(3) 返回集合中严格小于 3 的元素数量,即 2

os.find_by_order(2) 返回集合中第 2 小的元素,即 3。
这个是logn的
别的就没了

see you!

posted @ 2025-04-16 19:47  LteShuai  阅读(16)  评论(0)    收藏  举报