P4396 [AHOI2013] 作业 题解
题目链接:作业
其实可以类似“HH的项链”转化为偏序问题再 cdq 分治。不过这题感觉莫队然后值域分块很好写啊,基本不用动脑。
考虑查询的两个信息:
\(a \le x\le b\) 的 \(x\) 的个数。
\(a \le x \le b\) 的 \(x\) 的种类。
考虑优化莫队插入和查询复杂度,我们用值域分块。
值域分块常常有两种常见的写法:
修改:\(O(1)\),查询:\(\sqrt{V_{max}}\)。做法:信息维护每个块的信息,然后修改只需要修改特定的值域块信息,查询类似常规分块,同块暴力,不同块散块暴力,整块直接查询。
修改:\(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;
}
\]
P4396 [AHOI2013] 作业 题解的更多相关文章
- 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 & 3236 [Ahoi2013] 作业 题解
[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 978 Solved: 476 Descri ...
- 【题解】Luogu P4396 [AHOI2013]作业
原题传送门 最快的解法好像是cdq,但窝只会莫队+线段树/树状数组的做法 题目要我们求1.在区间[l,r]中值域在[a,b]中有多少个数2.在区间[l,r]中值域在[a,b]中有多少个不同数 一眼就看 ...
- bzoj 3236: 洛谷 P4396: [AHOI2013]作业 (莫队, 分块)
题目传送门:洛谷P4396. 题意简述: 给定一个长度为\(n\)的数列.有\(m\)次询问,每次询问区间\([l,r]\)中数值在\([a,b]\)之间的数的个数,和数值在\([a,b]\)之间的不 ...
- P4396 [AHOI2013]作业
题目链接 luogu4396 思路 唯有水题暖人心 咕了4天,今天跟着std对拍才做出来不得不说题解真的水的一批 先离散化一下 第一问差分询问,权值树状数组套一套就好了 \(nlog_{n}\) 第二 ...
- BZOJ3236:[AHOI2013]作业——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3236 第一种做法: 建两棵主席树分别处理两个问题. 第一个问题水,第二个问题参考SPOJ3267/ ...
- P4396 [AHOI2013]作业 分块+莫队
这个题正解是莫队+树状数组,但是我个人非常不喜欢树状数组这种东西,所以决定用分块来水这个题.直接在莫队维护信息的时候,维护单点同时维护块内信息就行了. 莫队就是这几行核心代码: void add(in ...
- 洛谷P4396 [AHOI2013]作业(树套树)
题意 题目链接 Sol 为什么一堆分块呀..三维数点不应该是套路离线/可持久化+树套树么.. 亲测树状数组套权值线段树可过 复杂度\(O(nlog^2n)\),空间\(O(nlogn)\)(离线) # ...
- luogu P4396 [AHOI2013]作业
目录 题目 思路 错误&&傻叉 代码 题目 luogu 思路 每次都是插入比之前所有数字大的数,所以之前的答案就不会改变 用fhq-treap求出原序列,然后用树状数组依次算出每个值得 ...
- 洛谷 P4396 [AHOI2013]作业
题目描述 题目传送门 分析 因为询问是关于区间的,并且没有强制在线,所以能用莫队解决 但是还要支持查询区间内大于等于 \(a\),小于等于 \(b\) 的数的个数和数值的个数 所以还要套一个数据结构 ...
- Bzoj 3236: [Ahoi2013]作业 莫队,分块
3236: [Ahoi2013]作业 Time Limit: 100 Sec Memory Limit: 512 MBSubmit: 1113 Solved: 428[Submit][Status ...
随机推荐
- 【每日一题】33. 简单瞎搞题 (滚动数组 + bitset 优化DP)
补题链接:Here 这个问题的难点在于如何统计出所有和可能出现的情况,并且不能重复. 很容易想到用桶去存储每一个数,即某个和能够组合出来则为1,否则为0 不妨令 \(dp[i][j]\) 表示为第 \ ...
- 30例 | 一文搞懂python日期时间处理
前言 datetime是python的内置模块,用来处理日期和时间. 该模块常用的类有: 类名 功能说明 date 日期对象 time 时间对象 datetime 日期时间对象 timedelta 时 ...
- d3过滤
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- 无向图求桥 UVA 796
***桥的概念:无向连通图中,如果删除某边后,图变 成不连通,则称该边为桥.*** ***一条边(u,v)是桥,当且仅当(u,v)为树枝边,且 满足dfn(u)<low(v)(前提是其没有重边) ...
- Spring boot 运行服务jar外配置配置文件方式总结
本文为博主原创,转载请注明出处: 由于需要在本地编译打包,在服务器上验证某些功能,需要频繁修改配置,本地打包时,会将配置文件也打包的jar 包内部,这种方式下,若修改配置则需要本地修改重新上传服务器一 ...
- Clickhouse执行处理查询语句(包括DDL,DML)的过程
Clickhouse执行处理查询语句(包括DDL,DML)的过程 总体过程 启动线程处理客户端接入的TCP连接: 接收请求数据,交给函数executeQueryImpl()处理: executeQue ...
- P5729 【深基5.例7】工艺品制作
1.题目介绍 [深基5.例7]工艺品制作 题目描述 现有一个长宽高分别为 \(w,x,h\) 组成的实心玻璃立方体,可以认为是由 \(1\times1\times1\) 的数个小方块组成的,每个小方块 ...
- 揭秘 Docker 网络:手动实现 Docker 桥接网络
本文将带领读者探索 Docker 桥接网络模型的内部机制,通过手动实现 veth pair.bridge.iptables 等关键技术,揭示网络背后的运作原理. 如果你对云原生技术充满好奇,想要深入了 ...
- Qt5.9 UI设计(二)——最简Qt工程搭建
前言 前面一章已经介绍了QT的开发环境的安装,这里介绍一下一个最简工程的搭建 操作步骤 新建项目 选择带界面的Qt Widgets Application 设置项目位置 注意这里的目录不能有中文路径 ...
- Docker下的资源限制问题
Docker下的资源限制问题 问题背景 公司某产品出现了一个奇怪的OOM 错误提示. 问题现象是 前台产品 提示 OOM cannot create native thread 但是同时查看 机器的资 ...