【LOJ#2402】[THUPC2017]天天爱射击(整体二分)

【LOJ#2402】[THUPC2017]天天爱射击(整体二分)

题面

LOJ

题解

显然对于每块木板可以二分被打烂的时间。
那么直接上整体二分处理就行了。

#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;
}
posted @ 2019-04-20 09:46  小蒟蒻yyb  阅读(939)  评论(0编辑  收藏  举报