LOJ#2402. 「THUPC 2017」天天爱射击 / Shooting 整体二分+树状数组
我之前一直以为这道题很厉害,没想到就是一个整体二分模板题,就当省选前练练手了.
我们计算每个木棍是被哪个子弹所击碎的,然后这个显然具有单调性.
每一条木棍分别去二分答案的话时间复杂度大概是 $O(n^2 \log n)$ 的.
所以我们就采用整体二分的方式,然后判断的话用一个树状数组来一个区间加法就好了.
然后整体二分的时候要处理好无解的情况.
code:
#include <bits/stdc++.h>
#define ll long long
#define N 200009
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,m;
int Ans[N],C[N],ar[N],bu[N];
struct node
{
int l,r,lim,id;
}s[N],ls[N],rs[N];
void update(int x,int v)
{
for(int i=x;i<N;i+=i&(-i))
C[i]+=v;
}
int query(int x)
{
int tmp=0;
for(int i=x;i;i-=i&(-i))
tmp+=C[i];
return tmp;
}
void solve(int l,int r,int L,int R)
{
if(l==r)
{
bu[l]=R-L+1;
return;
}
int mid=(l+r)>>1;
int tl=0,tr=0,x,y=L-1,z;
for(int i=l;i<=mid;++i) update(ar[i],1);
for(int i=L;i<=R;++i)
{
x=query(s[i].r)-query(s[i].l-1);
if(x>=s[i].lim) ls[++tl]=s[i];
else s[i].lim-=x,rs[++tr]=s[i];
}
for(int i=l;i<=mid;++i) update(ar[i],-1);
for(int i=1;i<=tl;++i) s[++y]=ls[i];
for(int i=1;i<=tr;++i) s[++y]=rs[i];
if(tl) solve(l,mid,L,L+tl-1);
if(tr) solve(mid+1,r,L+tl,R);
}
int main()
{
// setIO("input");
// freopen("input.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].lim),s[i].id=i;
for(int i=1;i<=m;++i) scanf("%d",&ar[i]);
ar[++m]=ar[1];
solve(1,m+1,1,n);
for(int i=1;i<m;++i) printf("%d\n",bu[i]);
return 0;
}

浙公网安备 33010602011771号