线段树的几种做法总结

线段树一些不太板的练手?

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;
		}
	}
}
posted @ 2024-09-11 18:38  lyrrr  阅读(20)  评论(0)    收藏  举报