我们发现,考虑每个子弹击碎哪些木板是不现实的,所以我们要转换问题:考虑每个木板被哪个子弹击碎
考虑可持久化线段树,转换问题成求区间\(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;
}
标签:THUPC2017,P7424,ll,tr,mid,pos,射击,jgt,find
From: https://www.cnblogs.com/pengchujie/p/17658955.html