和Leo一起做爱线段树的好孩子「FJ2014集训」圆桌会议

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

线段树维护霍尔定理

有霍尔定理知

l-r+1>=包含在区间内元素个数

所以想到线段树

把r-1移过去

这个时候线段树就在维护键值了

更新找区间最大值就好了

#include<bits/stdc++.h>
using namespace std;
inline void read(int &x){
    x=0;
    char ch=getchar();
    int f=1;
    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;
}
const int N=4e5+100;
#define lc (p<<1)
#define rc (p<<1|1)
int mmp[N<<2]={};
struct Data{
	int l,r,val;
}Q[N<<1];
int cnt=0;
struct Segment_Tree{
	struct Node{
		int lson,rson;
		int Mx;
		int lazy;
	}T[N<<2];
	inline void Clear(){
		memset(T,0,sizeof(T));
	}
	inline void PushUp(int p){
		T[p].Mx=max(T[lc].Mx,T[rc].Mx);
	}
	inline void PushDown(int p){
		if(T[p].lazy){
			T[lc].lazy+=T[p].lazy;
			T[rc].lazy+=T[p].lazy;
			T[lc].Mx+=T[p].lazy;
			T[rc].Mx+=T[p].lazy;
			T[p].lazy=0;
		}
	}
	inline void Build(int p,int l,int r){
		T[p].lson=l;
		T[p].rson=r;
		if(l==r){
			T[p].Mx=mmp[l]-1;
			T[p].lazy=0;
			return;
		}
		int mid=(l+r)/2;
		Build(lc,l,mid  );
		Build(rc,mid+1,r);
		PushUp(p);
	}
	inline void Update(int p,int l,int r,int val){
		if(l<=T[p].lson&&T[p].rson<=r){
			T[p].Mx+=val;
			T[p].lazy+=val;
			return;
		}
		PushDown(p);
		int mid=(T[p].lson+T[p].rson)/2;
		if(l<=mid)Update(lc,l,r,val);
		if(mid< r)Update(rc,l,r,val);
		PushUp(p);
	}
	inline int Query(int p,int l,int r){
		if(l<=T[p].lson&&T[p].rson<=r){
			return T[p].Mx;
		}
		PushDown(p);
		int mid=(T[p].lson+T[p].rson)/2;
		int Mx=-1;
		if(l<=mid)Mx=max(Mx,Query(lc,l,r));
		if(mid< r)Mx=max(Mx,Query(rc,l,r));
		return Mx;
	}
}Tree;
int n,m;
bool cmp (Data A,Data B){
	return A.r<B.r;
}
inline void Solve(){
	Tree.Clear();
	cnt=0;
	int sum=0;
	read(n);
	read(m);
	for(int i=1;i<=n;i++){
		read(Q[i].l);
		read(Q[i].r);
		read(Q[i].val);
		Q[i].l++;
		Q[i].r++;
		sum+=Q[i].val;
	}
	if(sum>m){
		puts("No");
		return;
	}
	int tot=n;
	for(int i=1;i<=n;i++){
		if(Q[i].r<Q[i].l)Q[i].r+=m;
		else{
			++tot;
			Q[tot]=Q[i];
			Q[tot].l+=m;
			Q[tot].r+=m;
		}
	}
	n=tot;
	for(int i=1;i<=tot;i++){
		mmp[++cnt]=Q[i].l;
		mmp[++cnt]=Q[i].r;
	}
	sort(mmp+1,mmp+1+cnt);
	int len=unique(mmp+1,mmp+1+cnt)-mmp-1;
	sort(Q+1,Q+1+tot,cmp);//cout<<"hh"<<'\n';
	Tree.Build(1,1,n<<1);
	
	for(int i=1;i<=n;i++){
//		cout<<Q[i].l<<" "<<Q[i].r<<'\n';
		Q[i].l=lower_bound(mmp+1,mmp+1+len,Q[i].l)-mmp;
		Q[i].r=lower_bound(mmp+1,mmp+1+len,Q[i].r)-mmp;
	}
	int flag=0;
	for(int i=1;i<=n;i++){
		Tree.Update(1,1,Q[i].l,Q[i].val);
		int Mx=Tree.Query(1,max(1,Q[i].r-m+1),Q[i].r);
		if(Mx>mmp[Q[i].r]){
//			cout<<i<<" "<<Mx<<" "<<mmp[Q[i].r]<<'\n';
			flag=1;
			break;
		}
	}
	if(flag==1){
		puts("No");
	}
	else puts("Yes");
}
int main(){
//	freopen("test.in","r",stdin);
	int Cas;
	read(Cas);
	while(Cas--){
		Solve();
	}
}

猜你喜欢

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