和Leo一起做爱线段树的好孩子【模拟试题】假期旅行

版权声明:LeoJAM Presents https://blog.csdn.net/fcb_x/article/details/82779771

额 set+线段树+st倍增

我好菜啊

这个是三元组,很明显set维护

但是要找到从l开始最远更新值

线段树维护区间最大值

然后建立ST表

倍增快速找到答案

#include<bits/stdc++.h>
#include<set>
using namespace std;
#define lc (p<<1)
#define rc (p<<1|1)
const int N=2e5+100;
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int n,m,k;
struct Node{
	int l,r,q;
}A[N];
bool operator < (Node A,Node B){
	return (A.l<B.l)||(A.l==B.l&&A.r<B.r);
}
struct Segment_Tree{
	struct Data{
		int l,r,sum;
		int lazy;
	}T[N<<2];
	void PushDown(int p){
		if(T[p].lazy){
			T[lc].sum=max(T[p].lazy,T[lc].sum);
			T[rc].sum=max(T[p].lazy,T[rc].sum);
			T[lc].lazy=max(T[p].lazy,T[lc].lazy);
			T[rc].lazy=max(T[p].lazy,T[rc].lazy);
			T[p].lazy=0;
		}
	}
	void Build(int p,int l,int r){
		T[p].l=l;
		T[p].r=r;
		if(l==r){
			T[p].sum=-1;
			return;
		}
		int mid=(l+r)>>1;
		Build(lc,l,mid);
		Build(rc,mid+1,r);
	}
	void Update(int p,int l,int r,int val){
		if(l<=T[p].l&&T[p].r<=r){
			T[p].sum=max(T[p].sum,val);
			T[p].lazy=max(T[p].lazy,val);
			return;
		}
		PushDown(p);
		int mid=(T[p].l+T[p].r)>>1;
		if(l<=mid)Update(lc,l,r,val);
		if(mid< r)Update(rc,l,r,val);
	}
	int Query(int p,int pos){
		if(T[p].l==pos&&T[p].r==pos){
			return T[p].sum;
		}
		PushDown(p);
		int mid=(T[p].l+T[p].r)>>1;
		if(pos<=mid)return Query(lc,pos);
		else return Query(rc,pos);
	}
}Tree;
set<Node> S[N];
int st[N][21];
int Find(int l,int r){
	int ans=0;
	for(int i=20;i>=0;i--){
		if(st[l][i]<r&&st[l][i]){
			ans+=(1<<i);
			l=st[l][i];
		}
	}
	if(st[l][0]>=r)return ans+1;
	else return -1;
}
int main(){
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
	read(n);
	read(m);
	read(k);
	Tree.Build(1,1,n);
	for(int i=1;i<=m;++i){
		read(A[i].l);
		read(A[i].r);
		read(A[i].q);
		S[A[i].q].insert(A[i]);
	}
	for(int i=1;i<=k;++i){
		set<Node> :: iterator It=S[i].begin();
		int last=1;
		for(;It!=S[i].end();++It){
			Node tmp=*It;
			int l=tmp.l;
//			if(last==2)cout<<"IN"<<" "<<last<<" "<<l<<' '<<i<<'\n';
			if(l>last)Tree.Update(1,last,l,l);
			last=max(last,tmp.r);
		}
		Tree.Update(1,last,n,n);
	}
	for(int i=1;i<=n;++i){
		st[i][0]=Tree.Query(1,i);
//		cout<<i<<" "<<st[i][0]<<'\n';
	}
	for(int j=1;j<=20;++j){
		for(int i=1;i<=n;++i){
			if(i+(1<<j)-1<=n){
				st[i][j]=st[st[i][j-1]][j-1];
			}
		}
	}
	int q;
	read(q);
	for(int i=1;i<=q;++i){
		int l,r;
		read(l);
		read(r);
		cout<<Find(l,r)<<'\n';
	}

}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/82779771