题目链接:作业

其实可以类似“HH的项链”转化为偏序问题再 cdq 分治。不过这题感觉莫队然后值域分块很好写啊,基本不用动脑。

考虑查询的两个信息:

  1. \(a \le x\le b\) 的 \(x\) 的个数。

  2. \(a \le x \le b\) 的 \(x\) 的种类。

考虑优化莫队插入和查询复杂度,我们用值域分块。

值域分块常常有两种常见的写法:

  1. 修改:\(O(1)\),查询:\(\sqrt{V_{max}}\)。做法:信息维护每个块的信息,然后修改只需要修改特定的值域块信息,查询类似常规分块,同块暴力,不同块散块暴力,整块直接查询。

  2. 修改:\(O(\sqrt{V_{max}})\),查询:\(O(1)\)。做法:维护前缀值域块和块内前缀信息,修改直接修改前缀信息。查询使用前缀和作差去查。

这两种都常常用于平滑修改和查询的复杂度。

本题中,使用莫队查询,修改显然需要 \(O(1)\),我们使用第一种即可。维护一个桶表示每种数的数量,每个值域块维护数量和种类两种信息,查询的时候就是常规分块查询了。

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

// #pragma GCC optimize("Ofast,unroll-loops")
// #pragma GCC optimize(2) #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 ansCnt[N], ansClass[N]; //两种答案
int pos[N]; //序列分块 struct Mo
{
int l, r, id, a, b; bool operator<(const Mo& other) const
{
return pos[l] ^ pos[other.l] ? l < other.l : pos[l] & 1 ? r < other.r : r > other.r;
}
} node[N]; //值域分块
constexpr int MX = 1e5;
constexpr int SIZE = sqrt(MX);
constexpr int CNT = (N + SIZE - 1) / SIZE;
int s[N], e[N], valPos[N]; //值域块的起点和终点、每个点对应值域块的编号
int cnt[N], valCnt[N], valClass[N]; //桶记录数量、值域块内数量、值域块内种类 inline void add(const int val)
{
int curr = valPos[val];
valCnt[curr]++;
if (cnt[val]++ == 0)valClass[curr]++;
} inline void del(const int val)
{
int curr = valPos[val];
valCnt[curr]--;
if (--cnt[val] == 0)valClass[curr]--;
} inline pii query(const int a, const int b)
{
const int currL = valPos[a], currR = valPos[b];
int ansCnt = 0, ansClass = 0;
if (currL == currR)
{
forn(i, a, b)ansCnt += cnt[i], ansClass += cnt[i] != 0;
return pii(ansCnt, ansClass);
}
forn(i, a, e[currL])ansCnt += cnt[i], ansClass += cnt[i] != 0;
forn(i, s[currR], b)ansCnt += cnt[i], ansClass += cnt[i] != 0;
forn(i, currL+1, currR-1)ansCnt += valCnt[i], ansClass += valClass[i];
return pii(ansCnt, ansClass);
} int n, q;
int val[N]; inline void solve()
{
cin >> n >> q;
int siz = sqrt(n);
forn(i, 1, n)cin >> val[i], pos[i] = (i - 1) / siz + 1;
forn(i, 1, q)
{
auto& [l,r,id,a,b] = node[i];
cin >> l >> r >> a >> b, id = i;
}
forn(i, 1, MX)valPos[i] = (i - 1) / SIZE + 1;
forn(i, 1, CNT)s[i] = (i - 1) * SIZE + 1, e[i] = i * SIZE;
e[CNT] = MX;
int l = 1, r = 0;
sortArr(node, q);
forn(i, 1, q)
{
auto [L,R,id,a,b] = node[i];
while (l > L)add(val[--l]);
while (l < L)del(val[l++]);
while (r < R)add(val[++r]);
while (r > R)del(val[r--]);
auto [fst, snd] = query(a, b);
ansCnt[id] = fst, ansClass[id] = snd;
}
forn(i, 1, q)cout << ansCnt[i] << " " << ansClass[i] << endl;
} signed int main()
{
// MyFile
Spider
//------------------------------------------------------
// clock_t start = clock();
int test = 1;
// read(test);
// cin >> test;
forn(i, 1, test)solve();
// while (cin >> n, n)solve();
// while (cin >> test)solve();
// clock_t end = clock();
// cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
}
\[时间复杂度为 \ O(m\times (\sqrt{n}+\sqrt{V_{max}}))
\]

P4396 [AHOI2013] 作业 题解的更多相关文章

  1. 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

    [原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 Descri ...

  2. 【题解】Luogu P4396 [AHOI2013]作业

    原题传送门 最快的解法好像是cdq,但窝只会莫队+线段树/树状数组的做法 题目要我们求1.在区间[l,r]中值域在[a,b]中有多少个数2.在区间[l,r]中值域在[a,b]中有多少个不同数 一眼就看 ...

  3. bzoj 3236: 洛谷 P4396: [AHOI2013]作业 (莫队, 分块)

    题目传送门:洛谷P4396. 题意简述: 给定一个长度为\(n\)的数列.有\(m\)次询问,每次询问区间\([l,r]\)中数值在\([a,b]\)之间的数的个数,和数值在\([a,b]\)之间的不 ...

  4. P4396 [AHOI2013]作业

    题目链接 luogu4396 思路 唯有水题暖人心 咕了4天,今天跟着std对拍才做出来不得不说题解真的水的一批 先离散化一下 第一问差分询问,权值树状数组套一套就好了 \(nlog_{n}\) 第二 ...

  5. BZOJ3236:[AHOI2013]作业——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3236 第一种做法: 建两棵主席树分别处理两个问题. 第一个问题水,第二个问题参考SPOJ3267/ ...

  6. P4396 [AHOI2013]作业 分块+莫队

    这个题正解是莫队+树状数组,但是我个人非常不喜欢树状数组这种东西,所以决定用分块来水这个题.直接在莫队维护信息的时候,维护单点同时维护块内信息就行了. 莫队就是这几行核心代码: void add(in ...

  7. 洛谷P4396 [AHOI2013]作业(树套树)

    题意 题目链接 Sol 为什么一堆分块呀..三维数点不应该是套路离线/可持久化+树套树么.. 亲测树状数组套权值线段树可过 复杂度\(O(nlog^2n)\),空间\(O(nlogn)\)(离线) # ...

  8. luogu P4396 [AHOI2013]作业

    目录 题目 思路 错误&&傻叉 代码 题目 luogu 思路 每次都是插入比之前所有数字大的数,所以之前的答案就不会改变 用fhq-treap求出原序列,然后用树状数组依次算出每个值得 ...

  9. 洛谷 P4396 [AHOI2013]作业

    题目描述 题目传送门 分析 因为询问是关于区间的,并且没有强制在线,所以能用莫队解决 但是还要支持查询区间内大于等于 \(a\),小于等于 \(b\) 的数的个数和数值的个数 所以还要套一个数据结构 ...

  10. Bzoj 3236: [Ahoi2013]作业 莫队,分块

    3236: [Ahoi2013]作业 Time Limit: 100 Sec  Memory Limit: 512 MBSubmit: 1113  Solved: 428[Submit][Status ...

随机推荐

  1. 2017年第八届 蓝桥杯A组 C/C++决赛题解

    蓝桥杯历年国赛真题汇总:Here 1. 平方十位数 由0~9这10个数字不重复.不遗漏,可以组成很多10位数字. 这其中也有很多恰好是平方数(是某个数的平方). 比如:1026753849,就是其中最 ...

  2. 无需代码绘制人工神经网络ANN模型结构图的方法

      本文介绍几种基于在线网页或软件的.不用代码的神经网络模型结构可视化绘图方法.   之前向大家介绍了一种基于Python第三方ann_visualizer模块的神经网络结构可视化方法,大家可以直接点 ...

  3. 基于python+django的求职招聘网站-网上招聘管理系统设计与实现

    该系统是基于python+django的求职招聘网站.网上招聘管理系统.网上人才招聘系统.毕业生求职招聘系统.大学生求职招聘系统.校园招聘系统.企业招聘系统.系统适合场景:大学生.课程作业.毕业设计. ...

  4. Oracle数据库同时建立和使用两个监听器

    1.问题 我分别对两个数据库实例(Lib和Orcl)各自建立了一个监听器,端口号分别为1520和1521,但是默认只启动一个,导致我切换数据库实例的时候, 出现以下问题:状态: 失败 -测试失败: I ...

  5. Linux-远程连接-ssh

  6. [转帖]技术分享 | MySQL:一文弄懂时区&time_zone

    https://opensource.actionsky.com/20211214-time_zone/   作者:胡呈清 爱可生 DBA 团队成员,擅长故障分析.性能优化,个人博客:https:// ...

  7. 有趣的Shell脚本学习

    有趣的Shell脚本学习 倒计时脚本 #!/bin/bash echo 20秒倒计时开始: tput sc # 循环40秒 for count in `seq 0 20` do tput rc tpu ...

  8. [转帖]如何对minio进行性能测试和分析

    https://developer.aliyun.com/article/1006775   环境详情 server(组成集群,ec为12:4) ip hosts 硬盘 storage01 172.1 ...

  9. 容器方式运行Mysql8.0.26的方法

    容器化运行Mysql8.0.26测试环境的方法 1. 前言 之前为了好处理,都是二进制包的方式安装mysql,但是有时候需要下载和安装也比较费时费力, 今天中午在弄Oracle RAC时想着以后能够容 ...

  10. 大数据平台Bug Bash大扫除最佳实践

    一.背景 随着越来越多的"新人"在日常工作以及大促备战中担当大任,我们发现仅了解自身系统业务已不能满足日常系统开发运维需求.为此,大数据平台部门组织了一次Bug Bash活动,既能 ...