【LOJ#2402】[THUPC2017]天天爱射击(整体二分)
题面
题解
显然对于每块木板可以二分被打烂的时间。
那么直接上整体二分处理就行了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 200200
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Board{int l,r,s,id;}p[MAX],tmp1[MAX],tmp2[MAX];
int n,m,ans[MAX],a[MAX],c[MAX];
const int N=2e5;
int lb(int x){return x&(-x);}
void add(int x,int w){while(x<=N)c[x]+=w,x+=lb(x);}
int getsum(int x){int s=0;while(x)s+=c[x],x-=lb(x);return s;}
void Solve(int l,int r,int L,int R)
{
if(L>R)return;
if(l==r)
{
for(int i=L;i<=R;++i)ans[p[i].id]=l;
return;
}
int mid=(l+r)>>1,t1=0,t2=0;
for(int i=l;i<=mid;++i)add(a[i],1);
for(int i=L;i<=R;++i)
{
int v=getsum(p[i].r)-getsum(p[i].l-1);
if(p[i].s<=v)tmp1[++t1]=p[i];
else p[i].s-=v,tmp2[++t2]=p[i];
}
for(int i=1;i<=t1;++i)p[L+i-1]=tmp1[i];
for(int i=1;i<=t2;++i)p[L+t1+i-1]=tmp2[i];
for(int i=l;i<=mid;++i)add(a[i],-1);
Solve(l,mid,L,L+t1-1);Solve(mid+1,r,L+t1,R);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)p[i].l=read(),p[i].r=read(),p[i].s=read(),p[i].id=i;
for(int i=1;i<=m;++i)a[i]=read();
Solve(1,m+1,1,n);
for(int i=1;i<=m;++i)c[i]=0;
for(int i=1;i<=n;++i)c[ans[i]]+=1;
for(int i=1;i<=m;++i)printf("%d\n",c[i]);
return 0;
}