【APIO2019】路灯(ODT & (树套树 | CDQ分治))
Description
一条 \(n\) 条边,\(n+1\) 个点的链,边有黑有白。若结点 \(a\) 可以到达 \(b\),需要满足 \(a\to b\) 的路径上的边不能有黑的。现给出 \(0\) 时刻边的初始状态,然后随后 \(1\sim q\) 时刻每时刻有一个事件或查询:
- \(\texttt{toggle} \ i\):翻转第 \(i\) 条边的颜色(黑 \(\Leftrightarrow\) 白)
- \(\texttt{query}\ a\ b\):查询从 \(0\) 开始到当前时刻,有多少时刻满足 \(a\) 可以到达 \(b\)。
对于每一个 \(\texttt{query}\),输出答案。
Hint
\(1\le n, q\le 3\times 10^5\)
Solution
设一个位置 \(x\) 可以到达的最左侧位置为 \(L(x)\),右侧为 \(R(x)\)。
这里有一个 用 set 维护连续段 的技巧——对于边状态 \(\texttt{0100011}\),可以分段存为:\([1, 1], [2, 2], [3,5], [6, 7]\) 四段。对于一个位置 \(x\),所属段为 \([l, r]\),那么有 \(L(x)=l, R(x)= r\)。(好像可以直接线段树)
当修改时,若将边 \(x\to x+1\) 变为白色,那么段 \([L(x), x],[x+1, R(x+1)]\) 间变为连通,可以将这两段删去,用 \([L(x), R(x+1)]\) 取而代之。对答案的影响?显然所有满足 \(a\in [L(x), x],b\in[x+1, R(x+1)]\) 的点对 \((a, b)\) 的答案都需要更改。
设当前时间为 \(t\),总时间为 \(T\)。
考虑如何将一个点对转化成一个二维点,而这又是本题的关键。这样一来,上面的修改变成了 **矩形加 ** 操作——左下点为 \((L(x), x+1)\),右上为 \((x, R(x))\) 的矩形区域的每个位置加上 \(T-t\),表明 暂定后面时刻都是连通的。
同理,若是白变黑,那么就是矩形减 \(T-t\)。表明目前看来,后面都不连通。
那么对于查询,只要获取位置 \((a, b)\) 的值即可。若当前两点是联通的,由于上文是暂定,于是还要把后面减掉,答案 \(-(T-t)\)。
如何高效执行上述两个操作?显然可以 CDQ 但我老写炸。不如树套树吧。把矩形修改差分成四个,单点询问转化成区域查询即可。
时空复杂度 \(O(n\log^2 n)\)。
Code
/*
* Author : _Wallace_
* Source : https://www.cnblogs.com/-Wallace-/
* Problem : APIO2019 路灯
*/
#include <cstdio>
#include <set>
using namespace std;
const int MaxN = 3e5 + 5;
int n, N, T;
bool dat[MaxN];
char str[MaxN];
namespace bit_seg {
const int S = MaxN << 9;
int lc[S], rc[S], total = 0, sum[S];
#define mid ((l + r) >> 1)
int root[MaxN];
#define lbt(x) (x & (-x))
void ins(int& x, int p, int v, int l, int r) {
if (!x) x = ++total;
sum[x] += v;
if (l == r) return;
if (p <= mid) ins(lc[x], p, v, l, mid);
else ins(rc[x], p, v, mid + 1, r);
}
void upd(int r, int c, int val) {
for (; r <= n; r += lbt(r)) ins(root[r], c, val, 1, n + 1);
}
void rectAdd(int xl, int yl, int xr, int yr, int val) {
upd(xl, yl, val);
upd(xr + 1, yr + 1, val);
upd(xl, yr + 1, -val);
upd(xr + 1, yl, -val);
}
int get(int x, int ql, int qr, int l, int r) {
if (!x) return 0;
if (ql <= l && r <= qr) return sum[x];
int ret = 0;
if (l <= mid) ret += get(lc[x], ql, qr, l, mid);
if (r > mid) ret += get(rc[x], ql, qr, mid + 1, r);
return ret;
}
int Query(int r, int c) {
int ret = 0;
for (; r; r -= lbt(r)) ret += get(root[r], 1, c, 1, n + 1);
return ret;
}
};
struct interval {
int l, r;
inline interval(int L, int R) : l(L), r(R) { }
inline bool operator < (const interval& x) const { return r < x.r; }
};
set<interval> itv;
typedef set<interval>::iterator Iter;
#include <algorithm>
signed main() {
scanf("%d%d", &n, &T), N = n++;
scanf("%s", str + 1);
for (int i = 1; i <= n; i++)
itv.insert(interval(i, i));
for (int i = 1; i <= N; i++) {
dat[i] = (str[i] == '1');
if (dat[i]) {
Iter it = --itv.lower_bound(interval(0, i + 1));
int L = it->l;
itv.erase(it), itv.erase(interval(i + 1, i + 1));
itv.insert(interval(L, i + 1));
}
}
for (Iter it = itv.begin(); it != itv.end(); it++)
bit_seg::rectAdd(it->l, it->l, it->r, it->r, T);
for (int t = 1; t <= T; t++) {
char opt[10];
int i, a, b;
scanf("%s", opt);
if (opt[0] == 't') {
scanf("%d", &i);
if (dat[i]) {
Iter it = itv.lower_bound(interval(0, i));
int l1 = it->l, r1 = i, l2 = i + 1, r2 = it->r;
bit_seg::rectAdd(l1, l2, r1, r2, -(T - t));
itv.erase(interval(l1, r2));
itv.insert(interval(l1, r1));
itv.insert(interval(l2, r2));
} else {
Iter it = itv.lower_bound(interval(0, i));
int l1 = it->l, r1 = i, l2 = i + 1, r2 = (++it)->r;
bit_seg::rectAdd(l1, l2, r1, r2, T - t);
itv.erase(interval(l1, r1));
itv.erase(interval(l2, r2));
itv.insert(interval(l1, r2));
}
dat[i] ^= 1;
} else {
scanf("%d%d", &a, &b);
int ans = bit_seg::Query(a, b);
if (itv.lower_bound(interval(0, a)) == itv.lower_bound(interval(0, b)))
printf("%d\n", ans - (T - t));
else printf("%d\n", ans);
}
}
}
【APIO2019】路灯(ODT & (树套树 | CDQ分治))的更多相关文章
- 【LOJ#3146】[APIO2019]路灯(树套树)
[LOJ#3146][APIO2019]路灯(树套树) 题面 LOJ 题解 考场上因为\(\text{bridge}\)某个\(\text{subtask}\)没有判\(n=1\)的情况导致我卡了\( ...
- BZOJ4170 极光(CDQ分治 或 树套树)
传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...
- 【Bzoj 3295】 动态逆序对(树套树|CDQ分治)
[题意] 每次删除一个数,然后问删除前逆序对数. [分析] 没有AC不开心.. 我的树状数组套字母树,应该是爆空间的,空间复杂度O(nlogn^2)啊..哭.. 然后就没有然后了,别人家的树套树是树状 ...
- bzoj3110: [Zjoi2013]K大数查询 【cdq分治&树套树】
模板题,折腾了许久. cqd分治整体二分,感觉像是把询问分到答案上. #include <bits/stdc++.h> #define rep(i, a, b) for (int i = ...
- bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...
- Codechef-ANCESTOR(树套树/CDQ分治)
题意: 给定两棵有根树,各有 N 个点.两棵树上的点分别被从 1 到 N 标号.两棵树的根均为标号为 1 的节点. 你的任务非常简单:对于每个 i,找到一个 j(j != i),使得在两棵树中 j 都 ...
- BZOJ 3262 cdq分治 OR 树套树
注意判断 三个条件都一样的-- (CDQ分治 其实并不是很难理解 只是想不到--) CDQ分治: //By SiriusRen #include <cstdio> #include < ...
- P5445 [APIO2019]路灯(树套树)
P5445 [APIO2019]路灯 转化为平面上的坐标(x,y),set维护连续区间. 用树套树维护矩阵加法,单点查询. 注意维护矩阵差分的时候, $(x,y,v)$是对$(x,y)(n+1,n+1 ...
随机推荐
- c++实现split
#include<iostream> #include<vector> #include<algorithm> #include<string> usi ...
- 源码分析:ReentrantReadWriteLock之读写锁
简介 ReentrantReadWriteLock 从字面意思可以看出,是和重入.读写有关系的锁,实际上 ReentrantReadWriteLock 确实也是支持可重入的读写锁,并且支持公平和非公平 ...
- 记一次ceph的故障修复(20160408)
ceph的在正常运行的时候基本不会出现故障,出现故障一般在变动的时候,具体有下面几种可能出现的情形 软件升级 增加存储节点 减少存储节点 调整副本数目 调整pg数目 磁盘出现损坏 节点网络出现异常 以 ...
- vue+node+mysql
准备工作 安装node,这是必须的 新版node自带npm,安装Node.js时会一起安装,npm的作用就是对Node.js依赖的包进行管理,也可以理解为用来安装/卸载Node.js需要装的东西.验证 ...
- JUC锁种类总结
在并发编程中有各种各样的锁,有的锁对象一个就身兼多种锁身份,所以初学者常常对这些锁造成混淆,所以这里来总结一下这些锁的特点和实现. 乐观锁.悲观锁 悲观锁 悲观锁是最常见的锁,我们常说的加锁指的也就是 ...
- redhat-NFS服务的配置与应用
---恢复内容开始--- 1.NFS服务简述 NFS实现Windows系统中资源共享的功能.NFS采用客户/服务器工作模式,客户端将服务器中的共享目录挂载到自己的某个目录下,这个目录可以与其他客户机的 ...
- bWAPP----HTML Injection - Reflected (POST)
bWAPP--low--HTML Injection - Reflected (POST) 只不过是把传递方式换成post, 防护的三个级别和内容与GET相同 1 function htmli($da ...
- PVE 下的虚拟机磁盘扩容
扩容背景:一台测试机磁盘不足,需要扩容: /dev/mapper/centos-root 40G 40G 20K 100% / 先到PVE网页上对需要扩容的机器扩容,这里新建20G示例: 另外之前也分 ...
- 需要登录才能下载的文件可以用Folx下载吗
用苹果电脑的小伙伴有没有发现,有时候文件即时有下载链接也还是要先登录才能下载,那这样的文件用下载器Folx还能下载码?下面小编将在Mac系统平台上,通过一篇教程教大家利用Folx 5的密码管理来保存网 ...
- 思维导图软件iMindMap怎么用模板制作思维导图
随着思维导图的不断发展,市场上相关的软件也越来越多.像XMind.MindManager等.每一款软件都有它独特的亮点.作为众多思维导图软件中的一款,iMindMap算是比较亮眼的了.现在很多人都在用 ...