线段树的几种做法总结
线段树一些不太板的练手?
hdu单峰数列
权值线段树
hdu第7场1007https://acm.hdu.edu.cn/showproblem.php?pid=7511
#include <iostream> #include <algorithm> #include <cstring> #include <vector> #include <set> #include <cmath> using namespace std; #define LL long long const int maxn=1e5+10; int t[maxn*50],ls[maxn*50],rs[maxn*50]; int root,tot; LL a[maxn]; int sufmx[maxn],sufmn[maxn],dp[maxn]; void push_up(int x){ t[x]=max(t[ls[x]],t[rs[x]]); } void upd(int &x,LL l,LL r,LL k,int id){ if(!x)x=++tot; if(l==r){ t[x]=id; return; } LL mid=(l+r)>>1; if(k<=mid) upd(ls[x],l,mid,k,id); else upd(rs[x],mid+1,r,k,id); push_up(x); } int que(int x,LL l,LL r,LL ql,LL qr){ if(l>=ql&&r<=qr){ return t[x]; } int res=0; LL mid=(l+r)>>1; if(ql<=mid)res=max(res,que(ls[x],l,mid,ql,qr)); if(qr>mid)res=max(res,que(rs[x],mid+1,r,ql,qr)); return res; } void solve(){ LL n,m,k;cin>>n>>m>>k; root=0; tot=0; for(int i=1;i<=n*50;i++)t[i]=0,ls[i]=0,rs[i]=0; t[0]=t[1]=0; for(int i=1;i<=n;i++){ cin>>a[i]; sufmx[i]=que(root,1,m,a[i],min(a[i]+k,m)); sufmn[i]=que(root,1,m,max(0LL,a[i]-k),a[i]); //cout<<sufmx[i]<<' '<<sufmn[i]<<endl; upd(root,1,m,a[i],i); } int q;cin>>q; while(q--){ int l,r;cin>>l>>r; int ans=0; for(int i=l;i<=r;i++)dp[i]=0; for(int i=l;i<=r;i++){ dp[i]=1; if(sufmx[i]>=l)dp[i]=max(dp[i],dp[sufmx[i]]+1); if(sufmn[i]>=l)dp[i]=max(dp[i],dp[sufmn[i]]+1); ans=max(ans,dp[i]); } cout<<r+1-l-ans<<endl; } } signed main() { int t;cin>>t;while(t--){ solve(); } }
最值线段树(扫描线)
牛客有两题
含有复杂合并的线段树
结训赛题https://www.luogu.com.cn/problem/T497333?contestId=189707
“分享一种很方便的需要合并复杂信息的线段树写法,考虑将每个节点的信息存入结构体,并实现一个合并两个结构体并返回合并后的函数,则查询时仅需将先后查到的区间对应的结构体直接调用函数合并起来即可,hdu 第三场我就是用的这个写法,比大力讨论好写一万倍。”-luckyblock
#include<bits/stdc++.h> #define ls(x) (x<<1) #define rs(x) ((x<<1)+1) #define mid ((l+r)>>1) using namespace std; int read(){ char c=getchar();int f=1;int res=0; while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ res=res*10+c-'0';c=getchar(); } return res*f; } const int maxn=2e5+10; struct node{ int cnt; bool is01,isl0,isr1; }t[maxn*4],base[3]; int a[maxn]; node merge(const node &x,const node &y){ node ret; if(!x.is01&&!y.is01){ return base[2]; } ret.cnt=x.cnt+y.cnt+(x.isr1&y.isl0); ret.is01=1; ret.isl0=x.is01?x.isl0:y.isl0; ret.isr1=y.is01?y.isr1:x.isr1; return ret; } int change(char x){ if(x=='<')return 0; if(x=='(')return 1; return 2; } void build(int x,int l,int r){ if(l==r){ t[x]=base[a[l]]; return; } build(ls(x),l,mid); build(rs(x),mid+1,r); t[x]=merge(t[ls(x)],t[rs(x)]); } void modify(int x,int l,int r,int k){ if(l==r){ t[x]=base[a[k]]; return; } if(k<=mid)modify(ls(x),l,mid,k); else modify(rs(x),mid+1,r,k); t[x]=merge(t[ls(x)],t[rs(x)]); } node query(int x,int ql,int qr,int l,int r){ if(l>=ql&&r<=qr)return t[x]; if (ql<=mid&&mid+1<=qr) { node ret1=query(ls(x),ql,qr,l,mid); node ret2=query(rs(x),ql,qr,mid+1,r); return merge(ret1,ret2); } if (ql<=mid) return query(ls(x),ql,qr,l,mid); return query(rs(x),ql,qr,mid+1,r); } signed main(){ //0 < 1 ( 2 = base[0]=(node){0,1,1,0}; base[1]=(node){0,1,0,1}; base[2]=(node){0,0,0,0}; int n,m;string s; cin>>n>>m>>s; for(int i=1;i<=n;i++){ a[i]=change(s[i-1]); } build(1,1,n); while(m--){ int x;cin>>x; if(x==1){ cin>>x;char c;cin>>c; a[x]=change(c); modify(1,1,n,x); } else{ int l,r;cin>>l>>r; cout<<query(1,l,r,1,n).cnt<<endl; } } }
分类:
E - 数据结构 / 线段树
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端