洛谷P7424题答案(天天爱射击)

题目描述

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

一只新手的答案(>_<)

多多指教,不喜勿喷;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值