小 W 准备参加 ION,他认为这是之前所有比赛的决赛,所以要认真准备。他有 N 阶段训 练计划,每一阶段训练计划可以表示为:需要训练编号为 l[i]到 r[i]之间的能力 s[i]天。他还找到了 M 类题目,每一类题目可以表示为:可以训练编号为 l[i]到 r[i]之间的能力,并且这样的一类题目有 k[i]道。 现在小 W 要给每天的训练安排一道题目(同一道题目只能使用一次,每天也只需要使用一道题目),使得题目训练的能力能完全包含需要训练的能力。如果可以达成输出“Yes”, 否则输出“No”。
输入格式:
第一行一个整数 T,表示数据组数。 每组数据第一行两个整数 N,M,分别表示训练的阶段数和题目的种数。 接下来 N 行,每行三个整数 l[i],r[i],s[i],描述一个阶段的训练。 接下来 M 行,每行三个整数 l[i],r[i],k[i],描述一类题目。
输出格式:
共 T 行,每行一个字符串“Yes”或“No”(不包含引号),表示一组数据的答案。
输入样例#1: 复制
3
2 2
1 4 2
3 5 1
1 4 2
2 5 1
3 2
1 3 1
2 4 1
3 5 1
1 3 2
2 5 1
2 2
1 2 1
1 2 2
1 2 2
1 2 1
输出样例#1: 复制
Yes
No
Yes
【样例解释 1】 对于第一组数据,小 W 有三个阶段的训练计划。 第一个阶段需要训练编号为 1 到 4 的能力 2 天,每天各使用一道训练编号为 1 到 4 能力的 题。 第二个阶段需要训练编号为 3 到 5 的能力 1 天,使用一道训练编号为 2 到 5 能力的题。 【数据范围】 对于 100%的数据,保证 1<=l[i]<=r[i]<=10^9,1<=s[i],k[i]<=10^9,T<=50,1<=N,M<=5 10^4。 记∑N 为一个测试点中所有 N 的和,∑M 为一个测试点中所有 M 的和,有 1<=∑N,∑M<=4 10^5。
把 N+M 个区间按照左端点进行排序(左端点相同的情况下可用区间在前)。排序之后扫描
每个区间,如果是可用区间,那么相当于插入了 t[i]个权值为 r[i]的数;如果是询问区间相当
于找到权值大于等于 r[i]的 s[i]个数并删去,发现一定是贪心地删掉权值尽可能小的数。可以
使用线段树维护插入操作,删除的时候先在线段树上二分,然后区间赋值为 0。
#include
using namespace std;
const int MAXN = 4e5 + 10;
const int inf = 1e9;
struct info
{
int l , r , s;
int type;
} a[MAXN << 1];
int n , m;
template inline void chkmax(T &x , T y) { x = max(x , y); }
template inline void chkmin(T &x , T y) { x = min(x , y); }
template inline void read(T &x)
{
T f = 1; x = 0;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
x *= f;
}
inline bool cmp(info a , info b)
{
return a.l == b.l ? a.type > b.type : a.l < b.l;
}
int main()
{
#ifndef evenbao
freopen("c.in" , "r" , stdin);
freopen("c.out" , "w" , stdout);
#endif
int T;
read(T);
while (T--)
{
read(n); read(m);
for (int i = 1; i <= n; i++)
{
read(a[i].l);
read(a[i].r);
read(a[i].s);
a[i].type = 1;
}
for (int i = 1; i <= m; i++)
{
read(a[n + i].l);
read(a[n + i].r);
read(a[n + i].s);
a[n + i].type = 2;
}
sort(a + 1 , a + (n + m) + 1 , cmp);
set< pair > s;
s.clear();
bool ok = true;
for (int i = 1; i <= n + m; i++)
{
if (a[i].type == 2)
{
s.insert(make_pair(a[i].r , a[i].s));
continue;
} else
{
bool flg = false;
while (!s.empty())
{
set< pair > :: iterator it = s.lower_bound(make_pair(a[i].r , -inf));
if (it == s.end()) break;
pair tmp = (*it);
if (a[i].s > tmp.second)
{
s.erase(it);
a[i].s -= tmp.second;
} else
{
s.erase(it);
if (tmp.second - a[i].s > 0) s.insert(make_pair(tmp.first , tmp.second - a[i].s));
flg = true;
break;
}
}
if (!flg)
{
ok = false;
break;
}
}
}
if (ok) printf("Yes\n");
else printf("No\n");
}
return 0;
}
// luogu-judger-enable-o2
#include
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=50005;
int n,m,t;
long long ans,L;
struct Event{
int l,r,s,flag,id;
bool operator < (const Event& tmp)const{
if(l==tmp.l){
return flag>1;
if(mid>=sj) change(x<<1,l,mid,sj,tj,d);
if(mid+1<=tj) change(x<<1|1,mid+1,r,sj,tj,d);
pushup(x);
}
void query(int x,int l,int r,int sj,int tj)
{
if(sj<=l&&r<=tj){
ans+=T[x].w;
return;
}
if(T[x].lazy) pushdown(x);
int mid=l+r>>1;
if(mid>=sj) query(x<<1,l,mid,sj,tj);
if(mid+1<=tj) query(x<<1|1,mid+1,r,sj,tj);
pushup(x);
}
bool work(int sj,int res)
{
ans=0;
query(1,1,L+1,sj,L+1);
if(ans=res){
r=mid;
}
else l=mid+1;
}
ans=0;
query(1,1,L+1,sj,L+1);
if(ans==res){
change(1,1,L+1,sj,l,0);
}
else{
if(sj>t;
while(t--){
flag=1;
cin>>n>>m;
f(i,1,n){
cin>>a[i].l>>a[i].r>>a[i].s;
a[i].flag=1;
a[i].id=i;
h[i+i-1]=a[i].l;
h[i+i]=a[i].r;
}
f(i,n+1,n+m){
cin>>a[i].l>>a[i].r>>a[i].s;
a[i].flag=0;
a[i].id=i;
h[i+i-1]=a[i].l;
h[i+i]=a[i].r;
}
sort(h+1,h+1+(n+m)*2);
L=unique(h+1,h+1+(n+m)*2)-(h+1);
sort(a+1,a+1+n+m);
change(1,1,L+1,1,L+1,0);
f(i,1,n+m){
int pos=lower_bound(h+1,h+1+L,a[i].r)-h;
if(!a[i].flag){
change(1,1,L+1,pos,pos,a[i].s);
}
else{
if(work(pos,a[i].s)){
cout<<"No"<