【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;
}

猜你喜欢

转载自www.cnblogs.com/cjyyb/p/10739981.html