C37 线段树+二分 P4344 [SHOI2015] 脑洞治疗仪
视频链接:223 线段树+二分 [SHOI2015] 脑洞治疗仪_哔哩哔哩_bilibili
#include <iostream> #include <cstring> #include <algorithm> using namespace std; #define ls u<<1 #define rs u<<1|1 const int N=200005; int n,m,opt,l0,r0,l1,r1; struct tree{ int l,r; int sum,lmx,rmx,mx; int len,tag; }tr[N<<2]; //sum:区间1的个数 //lmx:区间左起0的长度 //rmx:区间右起0的长度 // mx:区间0的最长长度 //len:区间的长度 //tag:区间赋值标记,无标记:-1,有标记:0或1 void pushup(tree& u,tree l,tree r){ //上传 u.sum=l.sum+r.sum; u.lmx=l.sum ? l.lmx : l.len+r.lmx; u.rmx=r.sum ? r.rmx : r.len+l.rmx; u.mx=max(max(l.mx,r.mx),l.rmx+r.lmx); } void pd(int u,int k){ //操作区间 tree& t=tr[u]; if(k==0){ //区间赋值为0 t.mx=t.lmx=t.rmx=t.len; t.sum=0; t.tag=0; } else{ //区间赋值为1 t.mx=t.lmx=t.rmx=0; t.sum=t.len; t.tag=1; } } void pushdown(int u){ //下传 if(tr[u].tag==0) pd(ls,0),pd(rs,0); if(tr[u].tag==1) pd(ls,1),pd(rs,1); tr[u].tag=-1; } void build(int u,int l,int r){ //建树 tr[u]={l,r,1,0,0,0,r-l+1,-1}; if(l==r) return; int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); pushup(tr[u],tr[ls],tr[rs]); } void change(int u,int x,int y,int k){ //区修 if(x<=tr[u].l&&tr[u].r<=y){pd(u,k);return;} pushdown(u); if(tr[ls].r>=x)change(ls,x,y,k); if(tr[rs].l<=y)change(rs,x,y,k); pushup(tr[u],tr[ls],tr[rs]); } int q1(int u,int x,int y){ //查询1的个数 if(x<=tr[u].l&&tr[u].r<=y)return tr[u].sum; pushdown(u); if(y<tr[rs].l) return q1(ls,x,y); if(x>tr[ls].r) return q1(rs,x,y); return q1(ls,x,y)+q1(rs,x,y); } int q0(int u,int x,int y){ //查询0的个数 if(x<=tr[u].l&&tr[u].r<=y) return tr[u].len-tr[u].sum; pushdown(u); if(y<tr[rs].l) return q0(ls,x,y); if(x>tr[ls].r) return q0(rs,x,y); return q0(ls,x,y)+q0(rs,x,y); } void work(){ scanf("%d%d",&l1,&r1); int x=q1(1,l0,r0); //查询1的个数 if(x==0) return; //去掉会误填1 change(1,l0,r0,0); //全部变成0 int l=l1,r=r1+1; //二分答案 while(l+1<r){ int m=(l+r)>>1; q0(1,l1,m)<=x ? l=m:r=m; } change(1,l1,l,1); //填上1 } tree query(int u,int x,int y){ //区查 if(x<=tr[u].l&&tr[u].r<=y) return tr[u]; pushdown(u); if(y<tr[rs].l) return query(ls,x,y); if(x>tr[ls].r) return query(rs,x,y); tree T; //开一个临时节点,存储拼凑结果 pushup(T,query(ls,x,y),query(rs,x,y)); return T; } int main(){ scanf("%d%d",&n,&m); build(1,1,n); while(m--){ scanf("%d%d%d",&opt,&l0,&r0); if(opt==0) change(1,l0,r0,0); if(opt==1) work(); if(opt==2) printf("%d\n",query(1,l0,r0).mx); } return 0; }
分类:
C 数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!