题目

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

显然在断开或连上某一条边的时候只会对左右两边联通的点产生贡献,这个拿\(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. Jmeter-【JSON Extractor】-响应结果中一级key取值

    一.请求返回样式 二.取code值 三.查看结果

  2. 听说“辣鸡小隔膜”出V1.3了?

    点击下载zip就送屠龙宝刀升级脚本(Version 1.2) 点击下载zip就送倚天宝剑种子测试器(Version 1.2) 顺便膜一波orz::Kevin

  3. hdu多校第八场 1003 (hdu6659) Acesrc and Good Numbers 数论/打表

    题意: 对于某数k,若数字d在1-k中出现次数恰好为k,则称k为好数. 给定d,x,求x以内,对于d而言最大的好数.k范围1e18. 题解: 打表二分即可. 但是,1e18的表是没法打出来的,只能在o ...

  4. 创建用户, 使用crontab定时运行程序

    # 以创建一个名为openstack的用户为例子 sudo adduser openstack sudo adduser openstack sudo # 把openstack用户加到可以使用cron ...

  5. CentOS7 相关配置

    nginx 1.在线安装nginx yum install nginx 2.启动nginx服务 systemctl start nginx 3.防火墙设置 打开http防火墙:firewall-cmd ...

  6. scala 常用模式匹配类型

    模式匹配的类型 包括: 常量模式 变量模式 构造器模式 序列模式 元组模式 变量绑定模式等. 常量模式匹配 常量模式匹配,就是在模式匹配中匹配常量 objectConstantPattern{ def ...

  7. Auto.js淘宝领喵币

    最近,淘宝的新玩法,一直在充斥我的眼球,尤其是喵币的,盖楼... .... 于是就进去看了看,发现逛逛店铺,给好多喵币,但是要进20个,每个要15秒,好麻烦,于是就上网搜了一下,有没有脚本 因为之前搞 ...

  8. C++ vector操作--往列表中添加或更新内容

    有个列表,往里面添加内容,如果对象已存在,只更新其属性,否则添加新一项. #include <iostream> #include <string> #include < ...

  9. Spring Boot环境搭建。

    1.环境准备. jdk1.8 idea(如果不会激活可以看另外一篇:https://www.cnblogs.com/joeking/p/11119123.html) 2.打开idea 如果是idea的 ...

  10. css 苹方字体

    苹方-简 常规体 font-family: PingFangSC-Regular, sans-serif; 苹方-简 极细体 font-family: PingFangSC-Ultralight, s ...