题目链接:曼哈顿交易

比较容易想的题,观察下首先不带修改,考虑维护的东西:次数作为权值,这玩意很显然很难在线维护,考虑下离线算法。看到这种和次数有关的权值,典型的单点加入和删除是非常好找到变化的,那么就莫队离线算法吧。

考虑下莫队如何来做,涉及到权值第 \(k\) 大,解决方法挺多的,但时限容易知道莫队需要 \(O(1)\) 修改,不能带 \(\log\),但查询显然至多 \(q\) 次,记住了,需要 \(O(1)\) 修改,\(O(\sqrt{n})\) 查询用于平衡复杂度的往往都是值域分块。对次数作为权值的值域进行分块,分别维护每个块区间和,单点和,查询第 \(k\) 大,只需要先枚举权值块一直到能确定是哪个值域的权值块,再单点枚举,跟主席树上二分思路是一致的。然后值域比较大,想用桶记录次数离散化一下就好了。这里为了更好地快速拿到次数最多的作为次数作为的值域的上界,就是出现次数最多元素的次数,我们可以用个 \(map\) 同时去重,排序,在插入时找次数最大值。剩下的莫队单修就很好写了,去掉原次数的贡献,增加新次数以后,单点修改它对应的块的信息即可。可以预处理出序列块和值域块的基本信息,剩下的看代码注释即可。

参照代码
#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,unroll-loops")

#define isPbdsFile

#ifdef isPbdsFile

#include <bits/extc++.h>

#else

#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/list_update_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/exception.hpp>
#include <ext/rope> #endif using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tii;
typedef tuple<ll, ll, ll> tll;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef __int128 i128;
#define hash1 unordered_map
#define hash2 gp_hash_table
#define hash3 cc_hash_table
#define stdHeap std::priority_queue
#define pbdsHeap __gnu_pbds::priority_queue
#define sortArr(a, n) sort(a+1,a+n+1)
#define all(v) v.begin(),v.end()
#define yes cout<<"YES"
#define no cout<<"NO"
#define Spider ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define MyFile freopen("..\\input.txt", "r", stdin),freopen("..\\output.txt", "w", stdout);
#define forn(i, a, b) for(int i = a; i <= b; i++)
#define forv(i, a, b) for(int i=a;i>=b;i--)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define endl '\n'
//用于Miller-Rabin
[[maybe_unused]] static int Prime_Number[13] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; template <typename T>
int disc(T* a, int n)
{
return unique(a + 1, a + n + 1) - (a + 1);
} template <typename T>
T lowBit(T x)
{
return x & -x;
} template <typename T>
T Rand(T l, T r)
{
static mt19937 Rand(time(nullptr));
uniform_int_distribution<T> dis(l, r);
return dis(Rand);
} template <typename T1, typename T2>
T1 modt(T1 a, T2 b)
{
return (a % b + b) % b;
} template <typename T1, typename T2, typename T3>
T1 qPow(T1 a, T2 b, T3 c)
{
a %= c;
T1 ans = 1;
for (; b; b >>= 1, (a *= a) %= c)if (b & 1)(ans *= a) %= c;
return modt(ans, c);
} template <typename T>
void read(T& x)
{
x = 0;
T sign = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')sign = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
x *= sign;
} template <typename T, typename... U>
void read(T& x, U&... y)
{
read(x);
read(y...);
} template <typename T>
void write(T x)
{
if (typeid(x) == typeid(char))return;
if (x < 0)x = -x, putchar('-');
if (x > 9)write(x / 10);
putchar(x % 10 ^ 48);
} template <typename C, typename T, typename... U>
void write(C c, T x, U... y)
{
write(x), putchar(c);
write(c, y...);
} template <typename T11, typename T22, typename T33>
struct T3
{
T11 one;
T22 tow;
T33 three; bool operator<(const T3 other) const
{
if (one == other.one)
{
if (tow == other.tow)return three < other.three;
return tow < other.tow;
}
return one < other.one;
} T3() { one = tow = three = 0; } T3(T11 one, T22 tow, T33 three) : one(one), tow(tow), three(three)
{
}
}; template <typename T1, typename T2>
void uMax(T1& x, T2 y)
{
if (x < y)x = y;
} template <typename T1, typename T2>
void uMin(T1& x, T2 y)
{
if (x > y)x = y;
} constexpr int N = 1e5 + 10;
int cnt[N], Cnt_cnt[N], Sum_Cnt_cnt[N]; //次数,值域块的单点次数出现的次数数组,值域块的块区间次数出现的次数的区间和数组
int pos[N], valPos[N]; //每个位置序列块id,值域块id
int s[N], e[N]; //值域块的起点和终点
int idxSize, valSize; //序列块大小,值域块大小
int idxCnt, valCnt; //序列块数量,值域块数量
map<int, int> mp; //离散化,排序,找次数上界
hash2<int, int> mpVal; //记录值->下标
int n, q, mx; //mx为值域上界(权值为次数) struct Mo
{
int l, r, id, k; bool operator<(const Mo& other) const
{
return pos[l] != pos[other.l] ? pos[l] < pos[other.l] : pos[l] & 1 ? r < other.r : r > other.r;
}
} node[N]; inline int query(int k)
{
//遍历值域块
forn(id, 1, valCnt)
{
if (Sum_Cnt_cnt[id] >= k)
{
//单点遍历
forn(i, s[id], e[id])
{
if (Cnt_cnt[i] >= k)return i;
k -= Cnt_cnt[i];
}
}
else k -= Sum_Cnt_cnt[id];
}
return -1;
} inline void add(const int val)
{
int& oldCnt = cnt[val];
Cnt_cnt[oldCnt]--;
Sum_Cnt_cnt[valPos[oldCnt]]--;
oldCnt++;
Cnt_cnt[oldCnt]++;
Sum_Cnt_cnt[valPos[oldCnt]]++;
} inline void del(const int val)
{
int& oldCnt = cnt[val];
Cnt_cnt[oldCnt]--;
Sum_Cnt_cnt[valPos[oldCnt]]--;
oldCnt--;
Cnt_cnt[oldCnt]++;
Sum_Cnt_cnt[valPos[oldCnt]]++;
} int a[N];
int idx;
int ans[N]; inline void solve()
{
cin >> n >> q;
idxSize = sqrt(n);
idxCnt = (n + idxSize - 1) / idxSize;
forn(i, 1, n)cin >> a[i], mp[a[i]]++, uMax(mx, mp[a[i]]), pos[i] = (i - 1) / idxSize + 1; //顺便找到权值上界(次数最多为多少)
for (const auto val : mp | views::keys)mpVal[val] = ++idx;
valSize = sqrt(mx);
valCnt = (mx + valSize - 1) / valSize;
forn(i, 1, mx)valPos[i] = (i - 1) / valSize + 1;
forn(i, 1, valCnt)s[i] = (i - 1) * valSize + 1, e[i] = i * valSize;
e[valCnt] = mx;
forn(i, 1, n)a[i] = mpVal[a[i]]; //离散化
forn(i, 1, q)
{
auto& [l,r,id,k] = node[i];
cin >> l >> r >> k, id = i;
}
sortArr(node, q);
int l = 1, r = 0;
forn(i, 1, q)
{
auto [L,R,id,k] = node[i];
while (l > L)add(a[--l]);
while (r < R)add(a[++r]);
while (l < L)del(a[l++]);
while (r > R)del(a[r--]);
ans[id] = query(k);
}
forn(i, 1, q)cout << ans[i] << endl;
} signed int main()
{
Spider
//------------------------------------------------------
int test = 1;
// read(test);
// cin >> test;
forn(i, 1, test)solve();
// while (cin >> n, n)solve();
// while (cin >> test)solve();
}
\[时间复杂度显然为离散化+查询+修改:\ O(n\log{n}+q\sqrt{Cnt_{max}}+q\sqrt{n})
\]

P3730 曼哈顿交易 题解的更多相关文章

  1. 洛谷 P3730 曼哈顿交易

    https://www.luogu.org/problem/show?pid=3730 题目背景 will在曼哈顿开了一家交易所,每天,前来买卖股票的人络绎不绝. 现在,will想要了解持股的情况.由 ...

  2. AC日记——曼哈顿交易 洛谷 P3730

    曼哈顿交易 思路: 都是套路: 代码: #include <cmath> #include <cstdio> #include <cstring> #include ...

  3. [SCOI2013]摩托车交易 题解

    思路分析 为了让交易额尽量大,显然我们需要尽量多地买入.对于每个城市,到达这个城市时携带的黄金受到几个条件的影响:之前卖出的黄金,之前能买入的最多的黄金,前一个城市到当前城市的路径上的最小边权.既然不 ...

  4. POJ 1984 Navigation Nightmare 带全并查集

    Navigation Nightmare   Description Farmer John's pastoral neighborhood has N farms (2 <= N <= ...

  5. Codeforces Round #345 (Div. 2) C (multiset+pair )

    C. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...

  6. Codeforces Round #345 (Div. 1) A - Watchmen 容斥

    C. Watchmen 题目连接: http://www.codeforces.com/contest/651/problem/C Description Watchmen are in a dang ...

  7. D-Distance_2019牛客暑期多校训练营(第八场)

    题目链接 Distance 题意 1<=nmh,q<=1e5 q个操作 1 x y z往坐标里加入一个点 2 x y z查询距离该点最近的点的距离(曼哈顿距离) 题解 做法一 将要插入的点 ...

  8. HDU3085(双向BFS+曼哈顿距离)题解

    Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  9. Codeforces 1093G题解(线段树维护k维空间最大曼哈顿距离)

    题意是,给出n个k维空间下的点,然后q次操作,每次操作要么修改其中一个点的坐标,要么查询下标为[l,r]区间中所有点中两点的最大曼哈顿距离. 思路:参考blog:https://blog.csdn.n ...

  10. toodifficult 题解

    名字听起来十分厉害啊...一道lzz的提交答案题. 提答题,我们看看题目,给出一个解密程序,叫你加密. 每个点有一个加密的sample和一些要加密的文本. 从题目中我们可以得到一些信息: 加密后一般为 ...

随机推荐

  1. 关于 VS Code 用户自定义代码片段的官方 $ 命令记录

    关于 VS Code 的定义用户代码片段的部分 $ 命令 TM_SELECTED_TEXT:当前选定的文本或空字符串: 注:选定后通过在命令窗口点选「插入代码片段」插入. TM_CURRENT_LIN ...

  2. SpringCloud学习 系列十、服务熔断与降级(1-简介)

    系列导航 SpringCloud学习 系列一. 前言-为什么要学习微服务 SpringCloud学习 系列二. 简介 SpringCloud学习 系列三. 创建一个没有使用springCloud的服务 ...

  3. 一、swift对象存储环境搭建

    系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...

  4. C#之RabbitMQ

    本文内容整理自https://blog.csdn.net/by_ron/category_6167618.html RabbitMQ–环境搭建 能点进来相信你明白RabbitMQ是干什么的了,这个系列 ...

  5. node pressure and pod eviction

    0. overview There are too many guides about node pressure and pod eviction, most of them are specifi ...

  6. idea新建spring boot 项目右键无package及java类的选项

    新创建的spring boot项目,只有一个默认的资源目录及启动配置. 在 group 的目录下右键新建包路径时 ,发现没有package选项,也没有Java Class的选项: 解决办法: File ...

  7. Visual Studio实用的搜索、查找、替换技巧

    前言 对于.NET开发者而言Visual Studio是我们日常工作中比较常用的开发工具,掌握一些Visual Studio实用的搜索.查找.替换技巧可以帮助我们大大提高工作效率从而避免996. Vi ...

  8. [java] - JavaBeans 获取 session

    RegServlet // 保存到 session request.getSession().setAttribute("user", user); userinfo.jsp // ...

  9. Shell-case-in-分支

  10. [转帖]全表扫描却产生大量db file sequential read一例

    老熊 Oracle性能优化 2012-05-23 开发人员在进行新系统上线前的数据校验测试时,发现一条手工执行的SQL执行了超过1小时还没有返回结果.SQL很简单: SELECT * FROM MOB ...