problem

\(\mathtt {loj-3146}\)

题意概要:一条直线上有 \(n+1\) 个点和 \(n\) 条道路,每条道路连通相邻两个点。在 \(q\) 个时刻内,每个时刻有如下两种操作之一:

  • 切换某条道路的状态,即:若原来是连通的,则现在断开;若原来断开,则现在连通
  • 给出 \(x,y\),询问在这次询问之前,有多少个时刻满足 \(a\rightarrow b\) 的道路连通(即这一段的道路都连通)

\(n,q\leq 3\times 10^5\),时限 \(5s\)

Solution

切了前两题让我还以为今年apio能ak的说,这题没切主要是因为没有想到可以将若干段区间的和变为所有右端点的坐标减去所有左端点的坐标,之前一直在想如何计算修改对答案的贡献来着

在这题里,连接即一段存在区间的左端点,减去当前时刻 \(t\),断开即一段区间的右端点,加上当前时刻 \(t\)。特别的,当一次询问时若他们之间连通,则需要再次强行加上当前时刻 \(t\)。

考虑切换道路 \((x,x+1)\),找到 \(x\) 往左走的最远端 \(l\),与 \(x+1\) 往右走的最远端 \(r\),则这次切换的影响为:左端点在 \([l,x]\) 内,且右端点在 \([x+1,r]\) 内的所有区间。

放到平面上去就是一个矩形,而询问就是询问这个平面上的一个点。有时间、\(x\)、\(y\)共三维,用 \(CDQ+BIT\) 可做到 \(O(n\log^2n)\)。

Code

至于找到每个位置向左向右的最远点,用 \(set\) 维护一下所有的极长道路区间即可

//loj-3146
#include <bits/stdc++.h>
using namespace std;
#define lb(x) (x&(-x)) template <typename _tp> inline void read(_tp&x) {
char ch=getchar();x=0;while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
} const int N = 301000;
int n; namespace WK {
namespace BIT {
int d[N];
inline void add(int x, int v) {for(;x<=n;x+=lb(x)) d[x] += v;}
inline int qry(int x) {int r=0;for(;x;x^=lb(x))r+=d[x];return r;}
} struct node {
int op, x, y, v;
} q[N*4], b[N*4];
int Ans[N], Qs, tot; void qwq(int l, int r) {
if(l == r) return ;
int m = l + r >> 1;
qwq(l, m), qwq(m+1, r);
int t0 = l, t1 = m + 1;
int tt = l;
while(t0 <= m or t1 <= r) {
if((t0 <= m and t1 <= r and q[t0].x <= q[t1].x) or t1 > r) {
if(q[t0].op == 0)
BIT::add(q[t0].y, q[t0].v);
b[tt++] = q[t0++];
} else {
if(q[t1].op == 1)
Ans[q[t1].v] += BIT::qry(q[t1].y);
b[tt++] = q[t1++];
}
}
for(int i=l;i<=m;++i)
if(q[i].op == 0)
BIT::add(q[i].y, -q[i].v);
for(int i=l;i<=r;++i)
q[i] = b[i];
} void work() {
qwq(1, tot);
for(int i=1;i<=Qs;++i)
printf("%d\n", Ans[i]);
} inline void add_modify(int x0, int x1, int y0, int y1, int v) {
q[++tot] = (node) {0, x0, y0, +v};
q[++tot] = (node) {0, x0, y1+1, -v};
q[++tot] = (node) {0, x1+1, y0, -v};
q[++tot] = (node) {0, x1+1, y1+1, +v};
}
inline void add_query(int x, int y, int vl) {
q[++tot] = (node) {1, x, y, ++Qs};
Ans[Qs] = vl;
}
} char str[N]; bool st[N];
int Q; typedef pair<int,int> pii;
set <pii> c;
set <pii> :: iterator it, itr;
#define ins insert
#define ers erase namespace BIT {
int d[N];
inline void add(int x, int v) {for(;x<=n;x+=lb(x)) d[x] += v;}
inline int qry(int l, int r) {
int res = 0;
for(;l;l^=lb(l)) res -= d[l];
for(;r;r^=lb(r)) res += d[r];
return res;
}
} int main() {
read(n), read(Q);
scanf("%s", str+1);
str[++n] = '0';
for(int i=1;i<=n;++i) {
st[i] = str[i] == '1';
if(st[i]) BIT::add(i+1, +1);
}
for(int i=1,j;(j=i)<=n;i=j+1) {
while(j < n and st[j]) ++j;
c.ins(pii(i, j));
} char opt[7];
int x, y;
for(int i=1;i<=Q;++i) {
scanf("%s", opt);
if(opt[0] == 't') {
read(x);
if(st[x]) {
itr = c.upper_bound(pii(x, n+1)), --itr;
int l = itr->first, r = itr->second;
WK::add_modify(l, x, x+1, r, +i);
c.ers(itr), c.ins(pii(l, x)), c.ins(pii(x+1, r));
BIT::add(x+1, -1);
st[x] = false;
} else {
it = itr = c.upper_bound(pii(x, n+1)), --it;
int l = it->first, r = itr->second;
WK::add_modify(l, x, x+1, r, -i);
c.ers(it), c.ers(itr), c.ins(pii(l, r));
BIT::add(x+1, +1);
st[x] = true;
}
} else {
read(x), read(y);
WK::add_query(x, y, BIT::qry(x, y) == y-x ? +i : 0);
}
}
WK::work();
return 0;
}

题解-APIO2019路灯的更多相关文章

  1. 【LOJ#3146】[APIO2019]路灯(树套树)

    [LOJ#3146][APIO2019]路灯(树套树) 题面 LOJ 题解 考场上因为\(\text{bridge}\)某个\(\text{subtask}\)没有判\(n=1\)的情况导致我卡了\( ...

  2. P5445 [APIO2019]路灯(树套树)

    P5445 [APIO2019]路灯 转化为平面上的坐标(x,y),set维护连续区间. 用树套树维护矩阵加法,单点查询. 注意维护矩阵差分的时候, $(x,y,v)$是对$(x,y)(n+1,n+1 ...

  3. LOJ3146 APIO2019路灯(cdq分治+树状数组)

    每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...

  4. 题解-APIO2019桥梁

    problem \(\mathrm {loj-3145}\) 题意概要:给定一张 \(n\) 点 \(m\) 边的无向图,边有边权,共 \(q\) 次操作,每次会将第 \(x\) 条边的权值改为 \( ...

  5. 题解-APIO2019奇怪装置

    problem loj-3144 题意概要:设函数 \(f(t)\) 的返回值为一个二元组,即 \(f(t)=((t+\lfloor \frac tB\rfloor)\bmod A, t\bmod B ...

  6. P5445 [APIO2019]路灯

    传送门· 对于询问 $(a,b)$ ,感觉一维很不好维护,考虑把询问看成平面上的一个点,坐标为 $(a,b)$ 每个坐标 $(x,y)$ 的值表示到当前 $x$ 和 $y$ 联通的时间和 考虑一个修改 ...

  7. APIO2019简要题解

    Luogu P5444 [APIO2019]奇怪装置 看到这种题,我们肯定会想到\((x,y)\)一定有循环 我们要找到循环节的长度 推一下发现\(x\)的循环节长为\(\frac{AB}{B+1}\ ...

  8. 【APIO2019】路灯(ODT & (树套树 | CDQ分治))

    Description 一条 \(n\) 条边,\(n+1\) 个点的链,边有黑有白.若结点 \(a\) 可以到达 \(b\),需要满足 \(a\to b\) 的路径上的边不能有黑的.现给出 \(0\ ...

  9. 2021record

    2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...

随机推荐

  1. useEffect 实现 componentWillUnmount生命周期函数(四)

    在写React应用的时候,在组件中经常用到componentWillUnmount生命周期函数(组件将要被卸载时执行).比如我们的定时器要清空,避免发生内存泄漏;比如登录状态要取消掉,避免下次进入信息 ...

  2. 贪心:leetcode 870. Advantage Shuffle、134. Gas Station、452. Minimum Number of Arrows to Burst Balloons、316. Remove Duplicate Letters

    870. Advantage Shuffle 思路:A数组的最大值大于B的最大值,就拿这个A跟B比较:如果不大于,就拿最小值跟B比较 A可以改变顺序,但B的顺序不能改变,只能通过容器来获得由大到小的顺 ...

  3. flutter Switch组件 On/off 用于切换一个单一状态

    import 'package:flutter/material.dart'; class SwitchDemo extends StatefulWidget { @override _SwitchD ...

  4. 记一次腾讯云MySQL数据库数据回滚

    如题,因为操作人员的问题,需要对数据库数据进行回滚. 可以看到,设置了7天自动备份,且是物理冷备. 什么是物理冷备?科普一下: (1)热备:在数据库运行时,直接进行备份,对运行的数据库没有影响.(2) ...

  5. 宣化上人:大佛顶首楞严经四种清净明诲浅释(1)(转自学佛网:http://www.xuefo.net/nr/article23/230609.html)

    唐天竺·沙门般剌密帝译 宣化上人主讲 一九八三年四月十七日晚讲于万佛圣城 四种清净明诲,真实不虚 楞严经里的四种清净明诲:断淫.断杀.断偷.断妄,是息息相关的.若犯淫戒,就容易犯杀戒,也容易犯盗戒.妄 ...

  6. PhpStorm文本选择范围的纵向起始位置可选

    ide一般都有这个功能. Alt+Shift+insert开启这个功能,使用效果如下,红色是默认选择的范围,绿色是我们想要的

  7. 【Leetcode_easy】874. Walking Robot Simulation

    problem 874. Walking Robot Simulation solution1: 思路:1)如何表示移动的方向以及移动的位置坐标; 2)障碍物坐标如何检查;3)求解的是最大距离; cl ...

  8. jqweui Popup 使用说明

    使用步骤说明: 今天遇到一个问题,无论怎么点击一个图标都不会弹出对应的遮罩层,但是把示列代码拷贝过来又可以正常显示:结果是由于在复制的时候把 # 号弄掉了 错误操作展示: <a href=&qu ...

  9. kubectl exec 执行 容器命令

    格式如下: kubectl exec -it podName -c containerName -n namespace -- shell comand 1 创建目录 kubectl exec -it ...

  10. 获取本机IP地址[JavaScript / Node.js]

    --web客户端JavaScript <body onload="checkCookie()"></body> function getYourIP(){ ...