题目链接

题目描述

给你一个 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. 【Python】爬虫-Xpath

    Xpath 文章参考:https://www.cnblogs.com/mxjhaima/p/13775844.html#案例 安装 pip install lxml 引用 from lxml impo ...

  2. 【Mybatis】动态SQL

    目录 动态SQL if语句 动态SQL if+where语句 动态SQL if+set语句 动态SQL choose(when,otherwise)语句 动态SQL trim语句 动态SQL SQL片 ...

  3. 详解RISC v中断

    声明 本文为本人原创,未经许可严禁转载.部分图源自网络,如有侵权,联系删除. RISC-V 中断与异常 trap(陷阱)可以分为异常与中断.在 RISC v 下,中断有三种来源:software in ...

  4. 十大功能特性,助力开发者玩转API Explorer

    摘要:华为云API Explorer为开发者提供一站式API解决方案统一平台,集成华为云服务所有开放API,支持全量快速检索.可视化调试.帮助文档.代码示例等能力,帮助开发者快速查找.学习API和使用 ...

  5. PB从入坑到放弃(五)窗口使用技巧

    PB应用程序就是由许多共同协作完成特定任务的窗口组成的集合. 窗口在应用程序的开发工作中占有很大的比重,是非常重要的一个 PB 对象 一.窗口类型 窗口类型 描述 Main ①可以覆盖其他窗口,也可以 ...

  6. Java实现数组去重复的18种写法

    说明 数组(含List)去重复在日常工作中经常遇到,很多时候用到Set数据结构,但有时候我们需要针对数据进行干预,这时候就需要用其他的实现方式了.以下列出各种的去重方式,基本含括了所有情况. 源码下载 ...

  7. 【技术积累】Linux中的命令行【理论篇】【一】

    7z命令 命令介绍 7z命令是Linux系统中的一个压缩和解压缩工具,它可以用来创建.压缩和解压缩7z格式的文件.7z是一种高压缩率的文件格式,通常比其他常见的压缩格式(如zip和gzip)具有更高的 ...

  8. 笔记:KMP的复习

    Record 一个重要的字符串算法,这是第三次复习. 通过总结我认为之所以某个算法总是忘记,是因为大脑始终没有认可这种算法的逻辑(也就是脑回路). 本篇主要讲解从KMP的应用场景,再到算法知识,以及例 ...

  9. 使用 Habana Gaudi2 加速视觉语言模型 BridgeTower

    在对最先进的视觉语言模型 BridgeTower 进行微调时,使用 Optimum Habana v1.6, Habana Gaudi2 可以达到 近 3 倍于 A100 的速度.硬件加速的数据加载以 ...

  10. Tongweb远程调试

    最近,在对项目进行国产化时,要求springboot项目容器换成tongweb.在部署中,有个问题一直无法在本地重现,搜了下网上资料,基本没法实现,所以我整理了下.注意,项目包代码必须与本地代码保持一 ...