rt,样例没过
#include<bits/stdc++.h>
#define maxn 200010
using namespace std;
int n,m;
int c[maxn],a[maxn],ans[maxn];
struct query{int l,r,s;}q[maxn],q1[maxn],q2[maxn];
void add(int x,int y)
{
for(;x<=n;x+=x&-x)c[x]+=y;
}
int ask(int x)
{
int val=0;
for(;x;x-=x&-x)val+=c[x];
return val;
}
//ql,qr相当于当前处理的这部分询问的队列的首尾指针
//二分的答案是子弹的下标
void solve(int ql,int qr,int l,int r)
{
if(ql>qr)return;
if(l==r)
{
for(int i=ql;i<=qr;++i)
if(q[i].s==1&&q[i].l<=a[l]&&a[l]<=q[i].r)//二分结束,检查木板是否满足条件
ans[l]++;//答案是桶,表示当前子弹射出后有多少木板碎掉了
return;
}
int mid=(l+r)>>1;
int t1=0,t2=0;
for(int i=l;i<=mid;++i)add(a[i],1);
for(int i=ql;i<=qr;++i)
{
int x=ask(q[i].r)-ask(q[i].l-1);//查询此范围内的子弹数
if(q[i].s<=x)q1[++t1]=q[i];
else q[i].s-=x,q2[++t2]=q[i];//二分询问
}
for(int i=l;i<=mid;++i)add(a[i],-1);//每轮二分时才更新树状数组,为防止重复更新而先消除本轮影响
for(int i=1;i<=t1;++i)q[ql+i-1]=q1[i];//把ql~ql+t1-1的询问覆盖为二分出的左半部分
for(int i=1;i<=t2;++i)q[ql+t1+i-1]=q2[i];//把ql+t1~ql+t1+t2-1询问覆盖为二分出的右半部分
solve(ql,ql+t1-1,l,mid); solve(ql+t1,qr,mid+1,r);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;++i)
{
int x,y,s;
cin>>x>>y>>s;
q[i]=(query){x,y,s};
}
for(int i=1;i<=m;++i)cin>>a[i];
solve(1,n,1,m);
for(int i=1;i<=m;++i)cout<<ans[i]<<'\n';
return 0;
}