C109 整体二分+树状数组 P7424 [THUPC2017] 天天爱射击

视频链接:C109 整体二分+树状数组 P7424 [THUPC2017] 天天爱射击_哔哩哔哩_bilibili

 

 

Luogu P7424 [THUPC2017] 天天爱射击

复制代码
// 整体二分+树状数组 O(n*logn*logn)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=200005;
int n,m,cnt;
int l[N],r[N],s[N],ans[N];
struct Q{
  //木板: opt=1,[x,y]击穿s次碎掉
  //子弹: opt=0,x坐标,y编号
  int opt,x,y,s;
}q[N<<1],q1[N<<1],q2[N<<1];

struct BIT{ //树状数组
  int s[N];
  void add(int x,int v){ //点修
    for(;x<=N;x+=x&-x) s[x]+=v;
  }
  int sum(int x){ //前缀和
    int t=0;
    for(;x;x-=x&-x) t+=s[x];
    return t;
  }
}T;

void solve(int l,int r,int L,int R){
  if(l>r) return;
  if(L==R){  //统计子弹L击碎的木板数
    for(int i=l;i<=r;++i) if(q[i].opt)ans[L]++;
    return;
  }
  int mid=(L+R)>>1,p1=0,p2=0;
  for(int i=l;i<=r;++i){ //先枚举子弹,后枚举木板
    if(!q[i].opt){
      //若子弹编号<=mid,则分流到左边,维护左边贡献
      if(q[i].y<=mid)q1[++p1]=q[i],T.add(q[i].x,1);
      else q2[++p2]=q[i];
    }
    else{
      int t=T.sum(q[i].y)-T.sum(q[i].x-1);
      //若木板被击穿子弹数>=s,则分流到左边
      if(t>=q[i].s) q1[++p1]=q[i];
      else q[i].s-=t,q2[++p2]=q[i];
    }
  }
  for(int i=1;i<=p1;++i) //清除贡献
    if(!q1[i].opt) T.add(q1[i].x,-1);
  for(int i=1;i<=p1;++i) q[l+i-1]=q1[i];
  for(int i=1;i<=p2;++i) q[l+p1+i-1]=q2[i];
  solve(l,l+p1-1,L,mid);
  solve(l+p1,r,mid+1,R); //分治
}
int main(){
  scanf("%d%d",&n,&m); //n块木板,m个子弹
  for(int i=1;i<=n;++i)scanf("%d%d%d",&l[i],&r[i],&s[i]);
  for(int i=1,x;i<=m;++i)scanf("%d",&x),q[++cnt]={0,x,i};//子弹
  for(int i=1;i<=n;++i)q[++cnt]={1,l[i],r[i],s[i]}; //木板
  solve(1,cnt,1,m+1); //整体二分,不能击碎的木板分流到m+1区
  for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
}
复制代码

 

posted @   董晓  阅读(130)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2023-03-31 G60 Nim游戏 SG函数
点击右上角即可分享
微信分享提示