题目链接

题目描述

给你一个 01 串,有 \(q\) 个时刻,每个时刻要么把一位取反,要么问你在过去的所有时刻中有多少个时刻 \(a\) 和 \(b-1\) 之间都为 1。

题目分析

观察题目,我们会发现可以把全为 1 的段看做一个连通块,如果两个位置在一个块内则可以互相到达,修改某个位置的值就相当于把两边的连通块合并或者分裂。

但是我们此时并非维护一个动态的连通块,而是需要知道所有时刻的信息,但是如果又把所有时刻遍历一遍会超时,考虑能不能用空间换时间,储存下所有时刻的信息方便维护。

容易观察到,维护一个连通块的目的无非是为了检查某两个点联不联通,那么我们可以抛弃连通块,转而维护两个点联通的时间数,这看似有些暴力,毕竟从空间复杂度上看 \(n^2\) 规模就已经超标了,别急,让我们先看看题目怎么操作。

对于一个询问操作自然没什么好说的,那么对于修改操作则如先前所述是将两边连通块分裂或者合并,我们把操作更改一下,记 \(l_1\),\(r_1\),\(l_2\),\(r_2\) 分别为两边连通块的左右端点,则合并操作表示所有左端点在 \([l_1,r_1]\) 内,右端点在 \([l_2,r_2]\) 的点对以后都联通,分裂相反。

注意到受影响的点实际上在平面内构成一个矩形,而询问相当于单点求值,我们能不能把修改转化成对于矩形的修改呢?当然可以,我们把对于一个点实际有效的时间段抽出来看,它实际上可以差分成一次单点加和单点减。

记当前时刻为 \(t\),只要合并时把整个矩形加上 \(q-t\),分裂时减去 \(q-t\) 即可,差分后可以使用 cdq 分治或者树套树解决,另外要注意的是查询时如果还联通,由于不考虑以后的时间,要将答案减去 \(q-t\)。

那么左右联通块如何维护呢,其实很简单,要么模仿珂朵莉树用 set 维护,要么用一颗线段树维护查询时二分即可,笔者这里使用了线段树的写法,不过细节多而且复杂度较高,还是建议使用 set 维护。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<cstring>
#define ite set<pai>::iterator
#define N 300005
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int tot,num,sta[N];
int a[N],rt[N];
int n,q;
struct Node{
int ls,rs,sum;
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
#define s(x) tr[x].sum
}tr[N<<8];
int query(int x,int l,int r,int L,int R){
if(!x) return 0;
if(L>=l && R<=r)return s(x);
int mid=(L+R)>>1,ans=0;
if(l<=mid) ans+=query(ls(x),l,r,L,mid);
if(r>mid) ans+=query(rs(x),l,r,mid+1,R);
return ans;
}
void change(int &x,int p,int L,int R,int s){
if(!x) x=++tot;
s(x)+=s;if(L==R) return;
int mid=(L+R)>>1;
if(p<=mid) change(ls(x),p,L,mid,s);
else change(rs(x),p,mid+1,R,s);
}
int lowbit(int x){
return x&(-x);
}
int ask(int x,int y){
int ans=0;
while(x){
ans+=query(rt[x],1,y,1,n+2);
x-=lowbit(x);
}
return ans;
}
void add(int x,int y,int p){
while(x<=n){
change(rt[x],y,1,n+2,p);
x+=lowbit(x);
}
}
struct no{
int ls,rs,sum,l,r;
#define tls(x) t2[x].ls
#define trs(x) t2[x].rs
#define ts(x) t2[x].sum
#define tl(x) t2[x].l
#define tr(x) t2[x].r
}t2[N<<2];
void build(int &x,int l,int r){
x=++num;tl(x)=l;tr(x)=r;
if(l==r){ts(x)=sta[l];return;}
int mid=(l+r)>>1;
build(tls(x),l,mid);build(trs(x),mid+1,r);
ts(x)=ts(tls(x))+ts(trs(x));
}
void ct(int x,int p){
if(tl(x)==tr(x)) {ts(x)=sta[tl(x)];return;}
int mid=(tl(x)+tr(x))>>1;
if(p<=mid) ct(tls(x),p);
else ct(trs(x),p);
ts(x)=ts(tls(x))+ts(trs(x));
}
int qt(int x,int l,int r){
if(tl(x)>=l && tr(x)<=r) return ts(x);
int mid=(tl(x)+tr(x))>>1;int ans=0;
if(l<=mid) ans+=qt(tls(x),l,r);
if(r>mid) ans+=qt(trs(x),l,r);
return ans;
}
int findr(int x){
if(x==n) return n+1;
if(qt(1,x+1,x+1)==0) return x+1;
int l=x+1,r=n;
while(l<r){ int mid=(l+r+1)>>1;
if(qt(1,x+1,mid)==mid-x){
l=mid;
}
else r=mid-1;
}
return l+1;
}
int findl(int x){
if(x==1) return 1;
if(qt(1,x-1,x-1)==0){
return x;
}
int l=1,r=x-1;
while(l<r){
int mid=(l+r)>>1;
if(qt(1,mid,x-1)==x-1-mid+1) r=mid;
else l=mid+1;
}
return l;
}
void opti(int l,int r,int ll,int rr,int p){
add(l,r,p);add(ll+1,r,-p);add(l,rr+1,-p);add(ll+1,rr+1,p);
}
int main(){
n=read();q=read();int l,r;char ch;string s;
for(int i=1;i<=n;i++){cin>>ch;sta[i]=ch-'0';}
build(l,1,n);int st=0;
for(int i=1;i<=n;i++){
if(sta[i]==1 && sta[i-1]==0) st=i;
if(sta[i]==1 && sta[i+1]==0){
opti(st,st,i+1,i+1,q);
}
}
for(int i=1;i<=q;i++){
cin>>s;
if(s=="query"){
l=read();r=read();if(l==r){cout<<i<<endl;continue;}
int ans=ask(l,r);
if(qt(1,l,r-1)==(r-1-l+1)) ans+=i-q;
cout<<ans<<endl;
}
else{
l=read();
int ll=findl(l);
int rr=findr(l);
if(sta[l]==0)opti(ll,l+1,l,rr,q-i);
else opti(ll,l+1,l,rr,i-q);
sta[l]^=1;ct(1,l); }
}
}

P5445 [APIO2019] 路灯 题解的更多相关文章

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

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

  2. P5445 [APIO2019]路灯

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

  3. APIO2019简要题解

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

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

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

  5. 洛谷 P1220 关路灯 题解

    Description 有 $n$ 盏路灯,每盏路灯有坐标(单位 $m$)和功率(单位 $J$).从第 $c$ 盏路灯开始,可以向左或向右关闭路灯.速度是 $1m/s$.求所有路灯的最少耗电.输入保证 ...

  6. 题解-APIO2019路灯

    problem \(\mathtt {loj-3146}\) 题意概要:一条直线上有 \(n+1\) 个点和 \(n\) 条道路,每条道路连通相邻两个点.在 \(q\) 个时刻内,每个时刻有如下两种操 ...

  7. 洛谷P1220 关路灯 题解 区间DP

    题目链接:https://www.luogu.com.cn/problem/P1220 本题涉及算法:区间DP. 我们一开始要做一些初始化操作,令: \(p[i]\) 表示第i个路灯的位置: \(w[ ...

  8. 洛谷P1220关路灯题解

    题目 此题是一个状态转移方程还算比较多的一个区间DP,这个题也能启示我们如果某个状态不能够很好地解决问题,那么不妨试试再加一维,而且如果转移顺序不确定的话,可以试试记忆化搜索,说不定就可以比较容易的写 ...

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

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

  10. 2021record

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

随机推荐

  1. CentOS 30分钟部署免费在线客服系统

    前段时间我发表了一系列文章,开始介绍基于 .net core 的在线客服系统开发过程.期间有一些朋友希望能够给出 Linux 环境的安装部署指导,本文基于 CentOS 7.9 来安装部署. 我详细列 ...

  2. 【渗透测试】利用Cobalt Strike渗透Windows

    目标 在kali中使用Cobalt Strike对Windows进行渗透 机器环境 kali(服务端):192.168.175.129 win11(攻击机):192.168.175.128 win11 ...

  3. BugKu-Misc-Photo的自我修养

    下载附件 打开002文件夹,发现一张照片 看到PNG右下疑似有半个字符,怀疑PNG宽高被修改 拿到测PNG宽高的脚本 点击查看代码 import binascii import struct crcb ...

  4. JSGRID loaddata显示超级多空行

    这个逼问题困扰了我两天了 作为一个主后端的程序员 初体验前端技术栈真的麻之又麻 以防万一 请先确认 是不是和我一个情况 如果是 请往下看 首先 我们需要念一段咒语 json是json string是s ...

  5. Django App使用

    App - 基本使用 作用主要用于业务功能模块开发 创建App > python manage.py startapp app01 创建成功后默认生成以下文件 默认文件讲解: 1. models ...

  6. 树莓派使用Golang+MQ135检测室内空气质量

      MQ135是一个比较便宜的空气质量传感器,可以用在家庭以及工业场所中.树莓派是一个小巧但很强大的卡片电脑,基于Linux,同时提供了很多硬件接口,方便开发出各种电子产品.Golang是一款简单高效 ...

  7. 信创啊,信创。Solon 的 war 包,现在同时支持 jakarta.servlet(及 javax.servlet)容器了!

    Solon 是个神奇的项目,不是基于 Servlet 的.但是又很支持 Servlet,尤其是 war 包.打起来还挺方便的. 如果你是做信创的(听说,很多信创项目是用 war 部署到 tomcat ...

  8. 新一代开源流数据湖平台Apache Paimon入门实操-上

    @ 目录 概述 定义 核心功能 适用场景 架构原理 总体架构 统一存储 基本概念 文件布局 部署 环境准备 环境部署 实战 Catalog 文件系统 Hive Catalog 创建表 创建Catalo ...

  9. js 文字像打字一样缓缓出现

    点击查看代码 <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UT ...

  10. [论文阅读] 颜色迁移-Illuminant Aware Gamut-Based

    [论文阅读] 颜色迁移-Illuminant Aware Gamut-Based 文章: [Illuminant Aware Gamut-Based Color Transfer], [python代 ...