Solution -「NOIOL-S 2021」「洛谷 P7470」岛屿探险
\(\mathcal{Description}\)
Link.
给定序列 \(\{(a,b)_n\}\),\(q\) 组形如 \((l,r,c,d)\) 的询问,求
\]
\(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」岛屿探险的更多相关文章
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Solution -「POI 2010」「洛谷 P3511」MOS-Bridges
\(\mathcal{Description}\) Link.(洛谷上这翻译真的一言难尽呐. 给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
- 「洛谷3338」「ZJOI2014」力【FFT】
题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...
- 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】
题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...
- 「洛谷3870」「TJOI2009」开关【线段树】
题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...
随机推荐
- Thrift框架-安装
1.前言 今天接触了使用 PRC[远程过程调用协议]的Thrift 框架 ,留下随笔心得,这是安装篇 2.下载 去apache官网下载Thrift脚本编译程序,window则下载一个exe文件,然后 ...
- 安装Apache-storm-0.9.1-incubating图解教程
注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6596214331988247054/ 安装步骤 (1) 安装Zookeeper集群,可以参考前一篇文章,本文已安装 ...
- Object.keys()方法 返回对象属性数组
MDN语法 Object.keys(obj) 参数obj:要返回其枚举自身属性的对象. 返回值:一个表示给定对象的所有可枚举属性的字符串数组. 1.传入一个对象,返回的的是所有属性值 var obj2 ...
- Static 静态+this
(一):静态 1.Static修饰的都是静态的,都是类相关的,不需要new对象,直接采用类名.的方式访问 2.当一个属性是类级别的,所有对象的这个属性都是一样的,直接定义为静态 类=属性+方法 属性描 ...
- elasticsearch在linux上的安装,Centos7.X elasticsearch 7.6.2安装
本文环境:Elasticsearch7.6.2目前最先版本 centos7.X JDK1.8 elasticsearch介绍 官网:https://www.elastic.co/cn/pr ...
- python极简教程05:生成器和匿名函数
测试奇谭,BUG不见. 讲解之前,我先说说我的教程和网上其他教程的区别: 1 我分享的是我在工作中高频使用的场景,是精华内容: 2 我分享的是学习方法,亦或说,是指明你该学哪些.该重点掌握哪些内容: ...
- C语言字幕从外向中间汇聚
演示数据中多个字符,从两端向中间移动,向中间汇聚 简单,粗暴,先上代码: Sleep()函数属于<windows.h>头文件中. sizeof()函数求右下标:数组内是数字时,求右下标要- ...
- leetcode 986. 区间列表的交集
问题描述 给定两个由一些 闭区间 组成的列表,每个区间列表都是成对不相交的,并且已经排序. 返回这两个区间列表的交集. (形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合, ...
- sql语句 异常 Err] 1064 - You have an error in your SQL syntax;
在我们开发的工程中,有时候会报[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds ...
- 【失败的经验】在linux下编译opencv for android
cd /home/ahfu#选择opencv 3.4.6版本来编译wget https://github.com/opencv/opencv/archive/3.4.6.tar.gztar -zxvf ...