题解:传送门
要求任意子集均满足,我们考虑对于每一个区间[p,q](显然只有
Q=ri
时这个区间才有询问的意义,同时我们也有
P=lj
),所有[l,r]在[p,q]之内的a的和s应满足s<=q-p+1即s+p-1<=q,否则一定不满足Hall定理。于是我们把所有的区间按r升序排列,考虑枚举Q,维护
P=Lj
时的答案,我们每次做到区间[l,r]时,所有P=1…l的和s都增大了a,然后我们查询1…r的最大值是否<=r-l+1,用线段树维护即可。
把环复制一遍变成链的情况,注意特判掉询问总区间的情况,具体证明可见神犇blog
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline ll read(){
ll x=0,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();
return x*f;
}
int n,m,a[N<<2];
struct quer{
int l,r,a;
friend bool operator<(quer a,quer b){return a.r<b.r;}
}q[N<<1];
struct node{
int mx,add;
}tr[N<<4];
inline void pushup(int p){
tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
}
inline void build(int p,int l,int r){
tr[p].add=tr[p].mx=0;
if(l==r){tr[p].mx=a[l]-1;return;}
int mid=l+r>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);pushup(p);
}
inline void doadd(int p,int val){
tr[p].mx+=val;tr[p].add+=val;
}
inline void pushdown(int p){
if(!tr[p].add) return;
doadd(p<<1,tr[p].add);doadd(p<<1|1,tr[p].add);tr[p].add=0;
}
inline void add(int p,int l,int r,int x,int y,int val){
if(x<=l&&r<=y){doadd(p,val);return;}
int mid=l+r>>1;pushdown(p);
if(x<=mid) add(p<<1,l,mid,x,y,val);
if(y>mid) add(p<<1|1,mid+1,r,x,y,val);
pushup(p);
}
inline int qmax(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return tr[p].mx;
int mid=l+r>>1,res=0;pushdown(p);
if(x<=mid) res=max(res,qmax(p<<1,l,mid,x,y));
if(y>mid) res=max(res,qmax(p<<1|1,mid+1,r,x,y));
return res;
}
int main(){
// freopen("a.in","r",stdin);
int tst=read();
while(tst--){
n=read();m=read();int sum=0,tot=n;
for(int i=1;i<=n;++i){
q[i].l=read()+1,q[i].r=read()+1,q[i].a=read(),sum+=q[i].a;
if(q[i].l>q[i].r) q[i].r+=m;
else q[++tot].l=q[i].l+m,q[tot].r=q[i].r+m,q[tot].a=q[i].a;
}if(sum>m){puts("No");continue;}n=tot;tot=0;
for(int i=1;i<=n;++i) a[++tot]=q[i].l,a[++tot]=q[i].r;
sort(a+1,a+tot+1);tot=unique(a+1,a+tot+1)-a-1;
build(1,1,tot);sort(q+1,q+n+1);bool flag=1;
for(int i=1;i<=n;++i){
q[i].l=lower_bound(a+1,a+tot+1,q[i].l)-a;
q[i].r=lower_bound(a+1,a+tot+1,q[i].r)-a;
add(1,1,tot,1,q[i].l,q[i].a);int mx=qmax(1,1,tot,1,q[i].r);
if(mx>a[q[i].r]){flag=0;break;}
}puts(flag?"Yes":"No");
}return 0;
}