题目描述
小 C 爱上了一款名字叫做《天天爱射击》的游戏。如图所示,这个游戏有一些平行于 𝑥x 轴的木板。现在有一些子弹,按顺序沿着 𝑦y 轴方向向这些木板射去。第 𝑖i 块木板被 𝑆𝑖Si 个子弹贯穿以后,就会碎掉消失。一个子弹可以贯穿其弹道上的全部木板,特别的,如果一个子弹触碰到木板的边缘,也视为贯穿木板。
小 C 现在知道了游戏中 𝑛n 块木板位置,以及知道了 𝑚m 个子弹射击位置。现在问你每个子弹射出去以后,有多少木板会碎掉?
输入格式
从标准输入读入数据。
第一行两个整数 𝑛n 和 𝑚m,表示木板数量和子弹数量。其中 1 ≤ 𝑛,𝑚 ≤ 2×1051 ≤ n,m ≤ 2×105。
接下来 𝑛n 行,每行三个整数 𝑥1,𝑥2,𝑠x1,x2,s,表示每块木板的左端点 𝑥x 坐标、右端点 𝑥x 坐标,以及贯穿多少次会碎掉。其中保证 1 ≤ 𝑥_1 ≤ 𝑥_2 ≤ 2×105,1 ≤ 𝑠 ≤ 2×1051 ≤ x1 ≤ x2≤2×105,1≤s≤2×105。
接下来 𝑚m 行,每行一个整数 ,表示每个子弹的 𝑥x 坐标。子弹按照发射顺序给出。其中保证 1≤𝑥≤2×1051≤x≤2×105。
输出格式
输出到标准输出。
𝑚m 行,每行一个整数。表示每颗子弹射出去后,有多少木板碎掉。
输入输出样例
输入 #1
3 2 1 3 1 2 4 2 3 4 1 2 3
输出 #1
1 2
、提示:
AC答案代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m;
int l[N],r[N],s[N];
struct node{
int l,r,s,op,id;
}a[N*2],la[N*2],ra[N*2];
int tr[N];
int res[N];
int lowbit(int x){
return x&-x;
}
void add(int x,int c){
for(int i=x;i<=200000;i+=lowbit(i)) tr[i]+=c;
}
int query(int x){
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
void work(int lv,int rv,int l,int r){
if(l>r) return ;
if(lv==rv){
for(int i=l;i<=r;i++){
if(a[i].op) res[lv]++;
}
return;
}
int mid=lv+rv>>1;
int cntl=0,cntr=0;
for(int i=l;i<=r;i++){
if(a[i].op){
int now=query(a[i].r)-query(a[i].l-1);
if(now>=a[i].s) la[++cntl]=a[i];
else a[i].s-=now,ra[++cntr]=a[i];
}
else{
if(a[i].id<=mid) {
add(a[i].l,1);
la[++cntl]=a[i];
}
else ra[++cntr]=a[i];
}
}
for(int i=l;i<=r;i++){
if(!a[i].op && a[i].id<=mid) add(a[i].l,-1);
}
for(int i=1;i<=cntl;i++) a[l+i-1]=la[i];
for(int i=1;i<=cntr;i++) a[l+cntl+i-1]=ra[i];
work(lv,mid,l,l+cntl-1);
work(mid+1,rv,l+cntl,r);
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>l[i]>>r[i]>>s[i];
int cnt=0;
for(int i=1;i<=m;i++){
int x;
cin>>x;
a[++cnt]={x,0,0,0,i};
}
for(int i=1;i<=n;i++) a[++cnt]={l[i],r[i],s[i],1,i};
work(1,m+1,1,cnt);
for(int i=1;i<=m;i++) cout<<res[i]<<endl;
return 0;
}
一只新手的答案(>_<)
多多指教,不喜勿喷;