题解:P3968 [TJOI2014] 电源插排

news/2025/1/15 16:52:02/文章来源:https://www.cnblogs.com/redacted-area/p/18405331

题意

维护一个 \(01\) 串,初始均为 \(0\),支持:

  • 单点将 \(1\) 修改为 \(0\)
  • 查询区间中 \(1\) 的个数。
  • 查询最长且最靠右的连续 \(0\) 段的靠右的中点,并将其改为 \(1\)

分析

第一个操作和第二个操作显然使用动态开点线段树维护。

我们只需要解决第三个操作。

我们用平衡树存储连续的 \(0\) 段的左右端点。

维护两棵平衡树,一棵按区间的左端点从小到大排序,另一棵以区间长度为第一关键字,左端点为第二关键字从大到小排序。

询问的时候只需要在第二棵平衡树中取出其最大的元素。

考虑修改操作带来的影响。

单点修改为 \(1\) 会导致一段连续的 \(0\) 段断开成为至多 \(2\) 段。

分类讨论处理一下段的分裂情况。

单点修改为 \(0\) 会导致至多两段连续的 \(0\) 段合并为同一段。

在第一棵树上二分找出插入点前后的连续段,同样分类讨论一下段的合并情况。

时间复杂度 \(O(q\log n+q\log q)\)


发现平衡树只需要支持查前驱后继,所以可以使用 set 实现。

可以向 set 中加入两个哨兵区间 \([-1,-2],[n+2,n+1]\) 以避免越界分类讨论。

Code

#include<bits/stdc++.h>
using namespace std;struct SegT
{struct node{uint32_t sum;node *lc, *rc;node() {lc=rc=0; sum=0;}}*rt;#define mid ((l+r)>>1)#define lson x->lc, l, mid#define rson x->rc, mid+1, rvoid modify(node *&x, int l, int r, int p, int v){if(!x) x=new node;x->sum+=v;if(l==r) return;if(p<=mid) modify(lson, p, v);if(p>mid)  modify(rson, p, v);}uint32_t query(node *x, int l, int r, int L, int R){if(!x) return 0;if(L<=l&&r<=R) return x->sum;uint32_t ret=0;if(L<=mid) ret+=query(lson, L, R); if(R>mid)  ret+=query(rson, L, R); return ret;}
}tr;struct itv
{int l, r;int pos() {return (l+r+1)>>1;}itv(int L, int R) {l=L, r=R;}
};#define len(x) (x.r-x.l+1)struct cmp1{bool operator()(itv a, itv b)const{return a.l<b.l;}};
struct cmp2{bool operator()(itv a, itv b)const{return len(a)==len(b)?a.l>b.l:len(a)>len(b);}};set<itv, cmp1> s1;
set<itv, cmp2> s2;
map<int, int> pos;void emplace(int x, int y) {s1.emplace(x, y), s2.emplace(x, y);}
void emplace(itv &x) {s1.emplace(x), s2.emplace(x);}
void erase(itv &x) {s1.erase(x), s2.erase(x);}int main()
{ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int n, q, l, r, k;cin>>n>>q;emplace(1, n);emplace(-1, -2);emplace(n+2, n+1);while(q--){cin>>k;if(!k)cin>>l>>r, cout<<tr.query(tr.rt, 1, n, l, r)<<'\n';else{if(!pos[k]){auto seg=*s2.begin();erase(seg);int p=seg.pos();pos[k]=p;tr.modify(tr.rt, 1, n, p, 1);if(p!=seg.l) emplace(seg.l, p-1);if(p!=seg.r) emplace(p+1, seg.r);}else{int p=pos[k];pos[k]=0;tr.modify(tr.rt, 1, n, p, -1);auto it=s1.lower_bound({p, 0});auto seg2=*it, seg1=*--it;if(seg1.r==p-1&&seg2.l==p+1)erase(seg1), erase(seg2),emplace(seg1.l, seg2.r);else if(seg1.r==p-1) erase(seg1), emplace(seg1.l, p);else if(seg2.l==p+1) erase(seg2), emplace(p, seg2.r);else emplace(p, p);}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/794662.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2-5Java多态

Java 多态 多态是同一个行为具有多个不同表现形式或形态的能力。 多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:多态性是对象多种表现形式的体现。 现实中,比如我们按下 F1 键这个动作:如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档; 如果当前在 Wor…

【VMware by Broadcom】Fusion 产品下载汇总

Fusion 产品下载汇总(百度网盘)-『2024年9月9日更新』Fusion 产品版本 百度网盘VMware-Fusion-1.0.0-51348.dmg 链接:https://pan.baidu.com/s/1C8Qkr6nwV5rKrhpsv2JJ_A?pwd=t0kjVMware-Fusion-1.1.0-62573.dmgVMware-Fusion-1.1.1-72241.dmgVMware-Fusion-1.1.2-87978.dmg…

C#/.NET/.NET Core技术前沿周刊 | 第 4 期(2024年9.1-9.8)

前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿,助力技术成长与视野拓宽。欢迎投稿,推荐或自荐优质文章/项目/学习资源等。…

51nod 1051 最大子矩阵和

51nod 1051 最大子矩阵和 可以用前缀和容斥优化到 \(O(n^4)\),但是不够进行如下图操作:将每一列的数值都压缩到一维的数组上,就转换为求最大字段和问题,时间复杂度 \(O(n^3)\)。 看看代码就知道了。 #include <bits/stdc++.h> using namespace std; #define ll long …

VS中如何将本地代码上传到码云仓库

VS中如何将本地代码上传到码云仓库 方式一:点击“添加到源代码管理”VS底部栏点击“添加到源代码管理”,并选择“Git”选项在弹出窗口中,选择“其他→现有远程”选项,在右侧区域找到“远程URL”输入框,输入Gitee仓库地址,然后点击“创建并推送”按钮。此时项目目录会多出…

Linux下网络丢包故障定位

转载: 云网络丢包故障定位全景指南 硬件网卡丢包 Ring Buffer溢出如图所示,物理介质上的数据帧到达后首先由NIC(网络适配器)读取,写入设备内部缓冲区 Ring Buffer中,再由中断处理程序触发 Softirq 从中消费,Ring Buffer 的大小因网卡设备而异。当网络数据包到达(生产)…

第一次个人编程作业

github地址这个作业属于哪个课程 计科22级12班这个作业要求在哪里 作业要求链接这个作业的目标 遍历论文查重并封装成可执行文件,学习PSP和commit规范,学习测试和评估代码一、设计思路 文件结构:程序流程:实现逻辑:查找资料发现比较简单的实现是通过计算余弦向量来实现重复…

echart map图标切换多选,单选,默认选中

需求是echart默认地图选中之前的去过的城市,一开始多选,后面点击为单选const option = {tooltip: {trigger: item,formatter: {b}},series: [{type: map,roam : true,//是否开启缩放和平移zoom : 1,//当前视角缩放比例selectedMode: multiple, // 只允许单选// 设置为一张完整…

CH58x/CH59x/CH57x RF_PHY(2.4g)切换Channel发送接收

前言:在做某些应用的时候可能需要我们发送或者接收时切换对应的channel。 此次完成测试的平台在WCH的CH592F上完成的。 在工作发送过程中切换37、38、39三个信道进行轮询发送。具体需要使用最关键的函数是:RF_SetChannel 实现代码如下:if(events & channl_37_tx_evt){RF…

ArmSoM-Sige5 的 RK3576 SoC 主线内核支持进展

我们很高兴地宣布,基于 RK3576 SoC 的 ArmSoM-Sige5 开发板的主线内核支持,collabora正在稳步推进中。RK3576 SoC 是 Rockchip 家族的一员,其设计和功能与广受欢迎的 RK3588 相似,许多硬件模块都得到了复用,这为我们在主线内核中添加支持提供了有利条件。 RK3576主线内核…

P3579

今天有点高效啊,切数论题都这样喵? #include<bits/stdc++.h> using namespace std; int main() {int n,a,b,c,d,s,m;cin>>n;while(n--){cin>>a>>b>>c>>d; m=min(b,d);for(int i=1;i<=m;i++){i=min(b/(b/i),d/(d/i));//优化,只考虑b/…

机器学习作业

Ch3-K均值聚类算法 【9月4日】 学号:102102156 姓名:高涛 1. make_circles方法生成数据 1.1 源代码 from sklearn.cluster import KMeans from sklearn.datasets import make_circles, make_moons, make_blobs import matplotlib.pyplo…