版权声明: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();
}
}