P7424 [THUPC2017] 天天爱射击

发布时间 2023-08-26 16:13:33作者: 傻阙的缺

传送门

我们发现,考虑每个子弹击碎哪些木板是不现实的,所以我们要转换问题:考虑每个木板被哪个子弹击碎

考虑可持久化线段树,转换问题成求区间\(l\sim r\)的第s早发射的子弹,模板题

上代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=2e5+50,M=2e5;
ll n,m;
ll x1[N],x2[N],s[N];
struct jgt
{
	ll pos,ti;
}zd[N];
bool cmp(jgt t1,jgt t2)
{
	return t1.pos<t2.pos;
}
struct jgt1
{
	ll l,r,gs;
}tr[N*20];
ll rt[N],tot;
ll ans[N],sr[N];
void add(ll &now,ll last,ll l,ll r,ll x)
{
	now=++tot;
	tr[now]=tr[last];
	tr[now].gs++;
	if(l==r) return ;
	ll mid=(l+r)>>1;
	if(x<=mid) add(tr[now].l,tr[last].l,l,mid,x);
	else add(tr[now].r,tr[last].r,mid+1,r,x);
}
void find(ll now,ll last,ll l,ll r,ll x)
{
	if(l==r)
	{
		ans[l]++;
		return ;
	}
	if(tr[now].gs-tr[last].gs<x) return;
	ll mid=(l+r)/2;
	ll tzy=tr[tr[now].l].gs-tr[tr[last].l].gs;
	if(tzy>=x) find(tr[now].l,tr[last].l,l,mid,x);
	else find(tr[now].r,tr[last].r,mid+1,r,x-tzy);
}
int main()
{
	scanf("%lld %lld",&n,&m);
	for(ll i=1;i<=n;i++)
	scanf("%lld %lld %lld",&x1[i],&x2[i],&s[i]);
	for(ll i=1;i<=m;i++)
	{
		scanf("%lld",&zd[i].pos);
		zd[i].ti=i;
	}
	sort(zd+1,zd+m+1,cmp);
	for(ll i=1;i<=m;i++)
	add(rt[i],rt[i-1],1,m,zd[i].ti);
	ll l,r,mid,no;
	for(ll i=1;i<=n;i++)
	{
		l=0,r=m;
		while(l<r)
		{
			mid=(l+r+1)/2;
			if(zd[mid].pos<=x2[i]) l=mid;
			else r=mid-1;
		}
		no=l;
		l=0,r=m;
		while(l<r)
		{
			mid=(l+r+1)/2;
			if(zd[mid].pos>=x1[i]) r=mid-1;
			else l=mid;
		}
		find(rt[no],rt[l],1,m,s[i]);
	}
	for(ll i=1;i<=m;i++)
	printf("%lld\n",ans[i]);
	return 0;
}