\(\mathcal{Description}\)

  Link.

  给定序列 \(\{(a,b)_n\}\),\(q\) 组形如 \((l,r,c,d)\) 的询问,求

\[\Big|\{i\in[l,r]~\big|~a_i\oplus c\le \min\{b_i,d\}\}\Big|
\]

  \(n,q\le10^5\),\(a,b,c,d<2^{24}\)。

\(\mathcal{Solution}\)

  CDQ 不熟练欸……

  在 \(i\) 的限制条件中,最离谱的应该是 \(\le\min\{b_i,d\}\),再联系部分分,可以想到分别计算两种情况。把原序列当做单点修改,询问离线为前缀查询,发现这就是一个偏序对的贡献问题,外层套一个 CDQ 分治处理。

  接下来,我们需要应对动态插入和询问,分 \((a,b)\) 一定用 \(c\) 查询和 \(a\) 一定用 \((c,d)\) 查询两种情况写两棵不需要持久化的 Trie 树分别维护即可。

  复杂度 \(\mathcal O((n+q)\log(n+q)\log\max\{a,b,c,d\})\)。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <algorithm> #define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i ) inline int rint() {
int x = 0, f = 1, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x * f;
} template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} const int MAXN = 1e5, MAXWID = 23;
int n, q, a[MAXN + 5], b[MAXN + 5], qall, ans[MAXN * 2 + 5];
int otmp[MAXN * 3 + 5], ord[MAXN * 3 + 5]; struct Event {
int r, c, d, id;
Event(): r( 0 ), c( 0 ), d( 0 ), id( 0 ) {}
Event( const int r_, const int c_, const int d_, const int id_ ):
r( r_ ), c( c_ ), d( d_ ), id( id_ ) {}
inline bool operator < ( const Event& t ) const {
return r != t.r ? r < t.r : id < t.id;
}
} evt[MAXN * 3 + 5]; struct DTrie { // maintain a[i] xor c <= d.
static const int MAXND = 2.3e6;
int node, root, siz[MAXND + 5], ch[MAXND + 5][2];
DTrie() { clear(); }
inline void clear() { node = root = 1, siz[1] = ch[1][0] = ch[1][1] = 0; }
inline int crtnd() {
int u = ++node;
siz[u] = ch[u][0] = ch[u][1] = 0;
return u;
} inline void insert( int& u, const int x, const int d ) {
if ( !u ) u = crtnd();
++siz[u];
if ( ~d ) insert( ch[u][( x >> d ) & 1], x, d - 1 );
} inline int query( const int u, const int c, const int lim, const int d ) {
if ( !u ) return 0;
if ( !~d ) return siz[u];
int p = c >> d & 1, q = lim >> d & 1, ret = 0;
if ( q ) return siz[ch[u][p]] + query( ch[u][!p], c, lim, d - 1 );
else return query( ch[u][p], c, lim, d - 1 );
}
} dtr; struct BTrie { // maintain a[i] xor c <= b[i].
static const int MAXND = 2.3e6;
int node, root, tag[MAXND + 5], ch[MAXND + 5][2];
BTrie() { clear(); }
inline void clear() { node = root = 1, tag[1] = ch[1][0] = ch[1][1] = 0; }
inline int crtnd() {
int u = ++node;
tag[u] = ch[u][0] = ch[u][1] = 0;
return u;
} inline void insert( int& u, const int a, const int b, const int d ) {
if ( !u ) u = crtnd();
if ( !~d ) return void( ++tag[u] );
int p = a >> d & 1, q = b >> d & 1;
if ( q ) {
if ( !ch[u][p] ) ch[u][p] = crtnd();
++tag[ch[u][p]];
insert( ch[u][p ^ 1], a, b, d - 1 );
} else {
insert( ch[u][p], a, b, d - 1 );
}
} inline int query( const int u, const int c, const int d ) {
if ( !u ) return 0;
int ret = tag[u];
if ( !~d ) return ret;
return ret + query( ch[u][c >> d & 1], c, d - 1 );
}
} btr; inline void solve( const int l, const int r ) {
if ( l >= r ) return ;
int mid = l + r >> 1, i, j, k;
solve( l, mid ), solve( mid + 1, r );
btr.clear(), i = l, j = mid + 1, k = l;
while ( i <= mid || j <= r ) {
if ( j > r || ( i <= mid && evt[ord[i]].d <= evt[ord[j]].d ) ) {
if ( !evt[ord[i]].id ) {
btr.insert( btr.root, evt[ord[i]].c, evt[ord[i]].d, MAXWID );
}
otmp[k++] = ord[i++];
} else {
if ( evt[ord[j]].id ) {
ans[evt[ord[j]].id] +=
btr.query( btr.root, evt[ord[j]].c, MAXWID );
}
otmp[k++] = ord[j++];
}
}
dtr.clear(), i = mid, j = r;
while ( i >= l || j > mid ) {
if ( j == mid || ( i >= l && evt[ord[i]].d > evt[ord[j]].d ) ) {
if ( !evt[ord[i]].id ) {
dtr.insert( dtr.root, evt[ord[i]].c, MAXWID );
}
--i;
} else {
if ( evt[ord[j]].id ) {
ans[evt[ord[j]].id] +=
dtr.query( dtr.root, evt[ord[j]].c, evt[ord[j]].d, MAXWID);
}
--j;
}
}
rep ( i, l, r ) ord[i] = otmp[i];
} int main() {
n = rint(), q = rint();
rep ( i, 1, n ) {
int a = rint(), b = rint();
evt[++qall] = Event( i, a, b, 0 );
}
rep ( i, 1, q ) {
int l = rint(), r = rint(), c = rint(), d = rint();
evt[++qall] = Event( l - 1, c, d, ( i << 1 ) - 1 );
evt[++qall] = Event( r, c, d, i << 1 );
}
rep ( i, 1, qall ) ord[i] = i;
std::sort( evt + 1, evt + qall + 1 );
solve( 1, qall );
rep ( i, 1, q ) wint( ans[i << 1] - ans[( i << 1 ) - 1] ), putchar( '\n' );
return 0;
}

\(\mathcal{Details}\)

  好久没写这个板块了。

  且不谈考场上能不能解出这道题,给这道题留的思考时间短得明显不合理。一来是策略问题——明明知道难度可能无需,却还骗自己说别人都把 T1 切了然后想了半天;二来,有些不习惯 \(3.5h\) 这种到长不短的比赛时间。

  哎,今后尝试优化考试策略叭。

Solution -「NOIOL-S 2021」「洛谷 P7470」岛屿探险的更多相关文章

  1. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  2. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

  3. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  4. Solution -「POI 2010」「洛谷 P3511」MOS-Bridges

    \(\mathcal{Description}\)   Link.(洛谷上这翻译真的一言难尽呐.   给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...

  5. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  6. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  7. 「洛谷3338」「ZJOI2014」力【FFT】

    题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...

  8. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

  9. 「洛谷3870」「TJOI2009」开关【线段树】

    题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...

随机推荐

  1. 怎样在 CentOS/RHEL 7/6 上安装和配置 Sendmail 服务器

    在 CentOS 上,可以通过 mailx 命令 或 sendmail 命令来给因特网发送电子邮件. 关于前者的文章比较多,关于后者的文章比较少. 这里记录了我在 CentOS 7 上安装和配置 se ...

  2. 安装Cacti-plugin

    安装pluginunzip cacti-plugin-0.8.7e-PA-v2.6.zip -d cacti-plugin-archcp -R cacti-plugin-arch/* /data/ww ...

  3. Spark案例练习-UV的统计

    关注公众号:分享电脑学习回复"百度云盘" 可以免费获取所有学习文档的代码(不定期更新)云盘目录说明:tools目录是安装包res 目录是每一个课件对应的代码和资源等doc 目录是一 ...

  4. 利用js模拟用户的cookie信息保存

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6814761849708347907/ 默认已完成爬虫文档<爬虫学习文档顺序> 并简单搭建完展示页面和管 ...

  5. MINItest软件架构总结

    MINItest软件架构总结 ----helloWen MINItest软件架构总结1. Problem Description2. Analysis3. Solution3.1. 通过读取设备信息来 ...

  6. 求n以内最大的k个素数以及它们的和

    本题要求计算并输出不超过n的最大的k个素数以及它们的和. 输入格式: 输入在一行中给出n(10≤n≤10000)和k(1≤k≤10)的值. 输出格式: 在一行中按下列格式输出: 素数1+素数2+-+素 ...

  7. 《剑指offer》面试题10- II. 青蛙跳台阶问题

    问题描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该青蛙跳上一个 n 级的台阶总共有多少种跳法. 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008, ...

  8. 【刷题-LeeetCode】260. Single Number III

    Single Number III Given an array of numbers nums, in which exactly two elements appear only once and ...

  9. 【采坑小计】prometheus的remote write协议遇到的问题

    没有读懂源码以前,无脑试错总是效率很低的! 1.thanos receiver报store locally for endpoint : conflict 接口返回的日志: store locally ...

  10. 513. Find Bottom Left Tree Value

    Given a binary tree, find the leftmost value in the last row of the tree. Example 1: Input: 2 / \ 1 ...