数据结构杂题乱记
由于是杂题乱记所以题目大多数不会太难。
P2572 [SCOI2010] 序列操作
题目内容
给你一个
0 l r
区间赋值为 ;1 l r
区间赋值为 ;2 l r
区间取反,即 变 、 变 ;3 l r
询问区间 总数。4 l r
询问区间最长 连续段长度。
思路
看到区间赋值,珂朵莉树板子题,然后翻看讨论区,发现珂朵莉树被Hack了,于是老老实实打线段树。同色连续段问题,对于每个节点开一个三元组,表示区间最长连续段长度,以区间左端点为左边界的最长连续段长度,以区间右端点为右边界的最长连续段长度。合并直接做即可。由于有区间翻转,所以再保存一个
-
如果当前操作为
或 ,则清空其余标记然后赋值。 -
如果当前操作为
且该区间有 标记,删除 标记改为 标记,进行相应的赋值,不加 标记;有 标记同理。 -
如果当前操作为
且该区间没有 或 标记,则进行交换操作,然后对 标记取反,即无变为有、有变为无。
容易发现这样操作一个节点最多只会同时带有
代码
#include<bits/stdc++.h> using namespace std; #define il inline #define ri register int #define inf 0x3f3f3f3f int a,b,c[100001],u,v,w; struct node { int lid,rid,val; bool can; node operator +(const node &A) { register node rn; rn.val=max((*this).val,A.val); rn.val=max(rn.val,(*this).rid+A.lid); if((*this).can) { rn.lid=(*this).lid+A.lid; } else { rn.lid=(*this).lid; } if(A.can) { rn.rid=(*this).rid+A.rid; } else { rn.rid=A.rid; } rn.can=(*this).can&A.can; return rn; } }; struct Segment_Tree { #define N 400004 int left[N],right[N],num2[N]; bool lazy0[N],lazy1[N],lazy2[N]; node num0[N],num1[N]; il int ls(int x) { return x<<1; } il int rs(int x) { return x<<1|1; } il void pushup(int x) { num0[x]=num0[ls(x)]+num0[rs(x)]; num1[x]=num1[ls(x)]+num1[rs(x)]; num2[x]=num2[ls(x)]+num2[rs(x)]; } il void pushdown(int x) { if(lazy0[x]) { lazy0[x]=false; lazy1[ls(x)]=lazy2[ls(x)]=lazy1[rs(x)]=lazy2[rs(x)]=false; lazy0[ls(x)]=lazy0[rs(x)]=true; ri len=right[ls(x)]-left[ls(x)]+1; num0[ls(x)]={len,len,len,true}; num1[ls(x)]={0,0,0,false}; num2[ls(x)]=0; len=right[rs(x)]-left[rs(x)]+1; num0[rs(x)]={len,len,len,true}; num1[rs(x)]={0,0,0,false}; num2[rs(x)]=0; } if(lazy1[x]) { lazy1[x]=false; lazy0[ls(x)]=lazy2[ls(x)]=lazy0[rs(x)]=lazy2[rs(x)]=false; lazy1[ls(x)]=lazy1[rs(x)]=true; ri len=right[ls(x)]-left[ls(x)]+1; num0[ls(x)]={0,0,0,false}; num1[ls(x)]={len,len,len,true}; num2[ls(x)]=len; len=right[rs(x)]-left[rs(x)]+1; num0[rs(x)]={0,0,0,false}; num1[rs(x)]={len,len,len,true}; num2[rs(x)]=len; } if(lazy2[x]) { lazy2[x]=false; ri len=right[ls(x)]-left[ls(x)]+1; if(lazy0[ls(x)]||lazy1[ls(x)]) { swap(lazy0[ls(x)],lazy1[ls(x)]); if(lazy0[ls(x)]) { num0[ls(x)]={len,len,len,true}; num1[ls(x)]={0,0,0,false}; num2[ls(x)]=0; } else { num0[ls(x)]={0,0,0,false}; num1[ls(x)]={len,len,len,true}; num2[ls(x)]=len; } } else { num2[ls(x)]=len-num2[ls(x)]; swap(num1[ls(x)],num0[ls(x)]); lazy2[ls(x)]^=1; } len=right[rs(x)]-left[rs(x)]+1; if(lazy0[rs(x)]||lazy1[rs(x)]) { swap(lazy0[rs(x)],lazy1[rs(x)]); if(lazy0[rs(x)]) { num0[rs(x)]={len,len,len,true}; num1[rs(x)]={0,0,0,false}; num2[rs(x)]=0; } else { num0[rs(x)]={0,0,0,false}; num1[rs(x)]={len,len,len,true}; num2[rs(x)]=len; } } else { num2[rs(x)]=len-num2[rs(x)]; swap(num1[rs(x)],num0[rs(x)]); lazy2[rs(x)]^=1; } } } void build(int x,int lt,int rt) { left[x]=lt; right[x]=rt; if(left[x]==right[x]) { if(c[lt]) { num2[x]=1; num1[x]={1,1,1,true}; } else { num0[x]={1,1,1,true}; } return; } ri me=(lt+rt)>>1; build(ls(x),lt,me); build(rs(x),me+1,rt); pushup(x); } void add0(int x,int lt,int rt) { if(lt<=left[x]&&right[x]<=rt) { lazy1[x]=lazy2[x]=false; lazy0[x]=true; ri len=right[x]-left[x]+1; num0[x]={len,len,len,true}; num1[x]={0,0,0,false}; num2[x]=0; return; } pushdown(x); ri me=(left[x]+right[x])>>1; if(lt<=me) { add0(ls(x),lt,rt); } if(rt>me) { add0(rs(x),lt,rt); } pushup(x); } void add1(int x,int lt,int rt) { if(lt<=left[x]&&right[x]<=rt) { lazy0[x]=lazy2[x]=false; lazy1[x]=true; ri len=right[x]-left[x]+1; num0[x]={0,0,0,false}; num1[x]={len,len,len,true}; num2[x]=len; return; } pushdown(x); ri me=(left[x]+right[x])>>1; if(lt<=me) { add1(ls(x),lt,rt); } if(rt>me) { add1(rs(x),lt,rt); } pushup(x); } void add2(int x,int lt,int rt) { if(lt<=left[x]&&right[x]<=rt) { ri len=right[x]-left[x]+1; if(lazy0[x]||lazy1[x]) { swap(lazy0[x],lazy1[x]); if(lazy0[x]) { num0[x]={len,len,len,true}; num1[x]={0,0,0,false}; num2[x]=0; } else { num0[x]={0,0,0,false}; num1[x]={len,len,len,true}; num2[x]=len; } } else { num2[x]=len-num2[x]; swap(num1[x],num0[x]); lazy2[x]^=1; } return; } pushdown(x); ri me=(left[x]+right[x])>>1; if(lt<=me) { add2(ls(x),lt,rt); } if(rt>me) { add2(rs(x),lt,rt); } pushup(x); } int find1(int x,int lt,int rt) { if(lt<=left[x]&&right[x]<=rt) { return num2[x]; } pushdown(x); ri me=(left[x]+right[x])>>1,rn=0; if(lt<=me) { rn+=find1(ls(x),lt,rt); } if(rt>me) { rn+=find1(rs(x),lt,rt); } return rn; } node find2(int x,int lt,int rt) { if(lt<=left[x]&&right[x]<=rt) { return num1[x]; } pushdown(x); ri me=(left[x]+right[x])>>1; register node rn1={-1,-1,-1},rn2={-1,-1,-1}; if(lt<=me) { rn1=find2(ls(x),lt,rt); } if(rt>me) { rn2=find2(rs(x),lt,rt); } if(rn1.val>=0&&rn2.val>=0) { return rn1+rn2; } else { if(rn1.val>=0) { return rn1; } else { return rn2; } } } #undef N }st; int main() { scanf("%d%d",&a,&b); for(ri i=1;i<=a;i++) { scanf("%d",&c[i]); } st.build(1,1,a); while(b--) { scanf("%d%d%d",&u,&v,&w); v++; w++; switch(u) { case 0: { st.add0(1,v,w); break; } case 1: { st.add1(1,v,w); break; } case 2: { st.add2(1,v,w); break; } case 3: { printf("%d\n",st.find1(1,v,w)); break; } case 4: { printf("%d\n",st.find2(1,v,w).val); break; } } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!