题目

显然一个熟练的选手应该能一眼看出我们需要维护点对的答案

显然在断开或连上某一条边的时候只会对左右两边联通的点产生贡献,这个拿\(set\)维护一下就好了

那现在的问题就是怎么维护了

考虑一个非常\(sb\)的问题,我们只想知道一个点对\((x,y)\)从开始到某个时间\(t\)有多少个时间是联通的

如果\(i\)时刻\((x,y)\)突然联通了,那么我们就把答案加上\(t-i+1\),如果\(i\)时刻\((x,y)\)突然断开了,我们就把答案减去\(t-i+1\),正确性显然

于是我们只需要分别维护那些常数和加上了多少个当前时间就可以回答任意时刻的询问了

所以问题变成了矩阵加单点查,显然可以差分之后变成一个三维偏序问题,可以直接大力\(cdq\),当然也可以直接上树套树

代码

#include <bits/stdc++.h>
#define L first
#define R second
#define re register
#define LL long long
#define lb(x) ((x) & (-x))
#define mp std::make_pair
#define set_it std::set<pii>::iterator
inline int read() {
char c = getchar();
int x = 0;
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - 48, c = getchar();
return x;
}
typedef std::pair<int, int> pii;
const int maxn = 3e5 + 5;
const int M = maxn * 200;
std::set<pii> s;
int n, m, B, cnt;
char S[maxn], op[12];
int rt[maxn << 2];
LL g[M], A;
int h[M], l[M], r[M];
int ins(int now, int x, int y, int pos, int v, int w) {
if (!now)
now = ++cnt;
if (x == y) {
g[now] += v, h[now] += w;
return now;
}
int mid = x + y >> 1;
if (pos <= mid)
l[now] = ins(l[now], x, mid, pos, v, w);
else
r[now] = ins(r[now], mid + 1, y, pos, v, w);
g[now] = g[l[now]] + g[r[now]];
h[now] = h[l[now]] + h[r[now]];
return now;
}
void find(int now, int x, int y, int pos) {
if (!now)
return;
if (x == y) {
A += g[now];
B += h[now];
return;
}
int mid = x + y >> 1;
if (pos <= mid)
find(l[now], x, mid, pos);
else
find(r[now], mid + 1, y, pos), A += g[l[now]], B += h[l[now]];
}
void change(int x, int y, int a, int b) {
if (y > n)
return;
for (re int i = x; i <= n; i += lb(i)) rt[i] = ins(rt[i], 1, n, y, a, b);
}
void query(int x, int y) {
for (re int i = x; i; i -= lb(i)) find(rt[i], 1, n, y);
}
inline pii ask(int pos) {
s.insert(mp(pos, n + 1));
set_it it = s.find(mp(pos, n + 1));
--it;
s.erase(mp(pos, n + 1));
return *it;
}
inline void add(int x, int y, int lx, int ry, int t, int v) {
change(x, lx, v * (1 - t), v);
change(x, ry + 1, v * (t - 1), -1 * v);
change(y + 1, lx, v * (t - 1), -1 * v);
change(y + 1, ry + 1, v * (1 - t), v);
}
inline void getAns(int t) {
int x = read(), y = read();
if (x > y)
std::swap(x, y);
A = 0, B = 0;
query(x, y);
printf("%d\n", A + B * t);
}
int main() {
n = read() + 1, m = read();
scanf("%s", S + 1);
for (re int i = 1; i < n; i++) S[i] -= '0';
int t = 1;
for (re int i = 1; i <= n; i++)
if (!S[i])
s.insert(mp(t, i)), t = i + 1;
for (set_it it = s.begin(); it != s.end(); ++it) add((*it).L, (*it).R, (*it).L, (*it).R, 0, 1);
for (re int i = 1; i <= m; i++) {
scanf("%s", op);
if (op[0] == 'q')
getAns(i - 1);
if (op[0] == 't') {
int x = read();
pii ll = ask(x), rr = ask(x + 1);
if (!S[x]) {
add(ll.L, ll.R, rr.L, rr.R, i, 1);
s.erase(ll), s.erase(rr);
s.insert(mp(ll.L, rr.R));
} else {
add(ll.L, x, x + 1, rr.R, i, -1);
s.erase(ll);
s.insert(mp(ll.L, x));
s.insert(mp(x + 1, rr.R));
}
S[x] ^= 1;
}
}
return 0;
}

「APIO 2019」路灯的更多相关文章

  1. #3146. 「APIO 2019」路灯

    #3146. 「APIO 2019」路灯 题目描述 一辆自动驾驶的出租车正在 Innopolis 的街道上行驶.该街道上有 \(n + 1\) 个停车站点,它们将街道划分成了 \(n\) 条路段.每一 ...

  2. #3145. 「APIO 2019」桥梁

    #3145. 「APIO 2019」桥梁 题目描述 圣彼得堡市内所有水路长度总和约 282 千米,市内水域面积占城市面积的 7%.--来自维基百科 圣彼得堡位于由 \(m\) 座桥梁连接而成的 \(n ...

  3. #3144. 「APIO 2019」奇怪装置

    #3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个 ...

  4. 「APIO 2019」桥梁

    题目 三天终于把\(APIO\)做完了 这题还是比较厉害的,如果不知道这是个分块应该就自闭了 考虑一个非常妙的操作,按照操作分块 我们设一个闸值\(S\),把\(S\)个边权修改操作分成一块,把所有的 ...

  5. 【LOJ #3144】「APIO 2019」奇怪装置

    题意: 定义将一个\(t\)如下转换成一个二元组: \[ f(t) = \begin{cases} x = (t + \left\lfloor \frac{t}{B} \right \rfloor) ...

  6. 「APIO 2019」奇怪装置

    题目 考虑推柿子 最开始的想法是如果两个\(t\)在\(mod\ B\)意义下相等,那么只需要比较一下\((t+\left \lfloor \frac{t}{B}\rfloor \right)mod\ ...

  7. 「WC 2019」数树

    「WC 2019」数树 一道涨姿势的EGF好题,官方题解我并没有完全看懂,尝试用指数型生成函数和组合意义的角度推了一波.考场上只得了 44 分也暴露了我在数数的一些基本套路上的不足,后面的 \(\ex ...

  8. LOJ#3054. 「HNOI 2019」鱼

    LOJ#3054. 「HNOI 2019」鱼 https://loj.ac/problem/3054 题意 平面上有n个点,问能组成几个六个点的鱼.(n<=1000) 分析 鱼题,劲啊. 容易想 ...

  9. 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)

    [题解]#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT) 之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现, ...

随机推荐

  1. mui与springMVC前后端分离

    这个小dome简单来说的前后端分离,通过跨域调用接口来显示数据. 前端用到mui框架,主要来显示数据. 后端用到Java的springMVC,restful服务来做增删改查管理, 这里主要实现动态显示 ...

  2. LUOGU P3690 【模板】Link Cut Tree (lct)

    传送门 解题思路 \(lct\)就是基于实链剖分,用\(splay\)来维护每一条实链,\(lct\)的维护对象是一棵森林.\(lct\)支持很多神奇的操作: \(1.\) \(access\):这是 ...

  3. NX二次开发-UFUN将工程图中的点坐标映射到建模绝对坐标UF_VIEW_map_drawing_to_model

    #include <uf.h> #include <uf_ui.h> #include <uf_draw.h> #include <uf_view.h> ...

  4. Contos7 FTP 安装步骤

    1. 使用rpm -q vsftpd查看是否已安装2.如未安装使用yum -y install vsftpd安装3.修改ftp配置文件vim /etc/vsftpd/vsftpd.conf,修改内容如 ...

  5. 在360的兼容模式下关于innerHTML=“”,引发的问题

    innerHTML属性,可以动态设置和修改dom,但是在360的兼容模式下回存在一些问题...... var dBody = document.body; var fatherDom = docume ...

  6. flutter SnackBar

    无法弹出 snackbar时

  7. C语言进阶学习第三章

    以下记录动态内存分配: 1.malloc和free malloc和free分别用于执行动态内存分配和释放.这些函数维护一个可用内存池,当一个程序需要一些内存时,调用malloc函数,malloc从内存 ...

  8. sql2000行转列 转过来的测试完也不知那个网站去哪了 没法写出处了

    ALTER procedure dbo.CommonRowToCol ) as begin --必须包含colname列和result列(不区分大小写), --除colname列和result列 其余 ...

  9. python 17 异常

    自 http://www.cnblogs.com/BeginMan/p/3171445.html 一.什么是错误,什么是异常,它们两者区别 这里解释如下:个人觉得很通俗易懂 错误是指在执行代码过程中发 ...

  10. 天道神诀---防火墙以及selinux(上篇)

    Linux防火墙 linux6.x 防火墙会影响通信,默认是拒绝所有. [root@redhat6 sysconfig]# chkconfig iptables --listiptables      ...