LOJ2402 [THUPC2017] 天天爱射击 / Shooting 二分查找+主席树

题目链接:传送门

主席树模板题。
把子弹按照 x x x排序,另外记录一个 t t t,表示子弹射♂出去的时间qwq。
对于每块木板,设它左右端的 x x x坐标分别为 x 1 , x 2. x1,x2. x1,x2.
二分查找出子弹在 [ x 1 , x 2 ] [x1,x2] [x1,x2]区间内的部分,记为 [ l , r ] [l,r] [l,r]
因为子弹是按照时间顺序射♂出去的,所以问题就转化为在 [ l , r ] [l,r] [l,r]区间内求第 s s s小值。
然后上主席树板子即可。
注:如果 [ l , r ] [l,r] [l,r]区间长度小于当前木板的 s s s,要 c o n t i n u e continue continue掉qwq

代码

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#define re register int
#define rl register ll
using namespace std;
typedef long long ll;
ll read() {
	rl x=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9') {
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9') {
		x=10*x+ch-'0';
		ch=getchar();
	}
	return x*f;
}
namespace I_Love {
 
const int Size=200005;
const int LOG=20;
int n,m,damage[Size];
struct plank {
	int x1,x2,s;
} wood[Size];
struct bullet {
	int x,t;
	inline bool operator < (const bullet b) const {
		return x<b.x;
	}
	inline bool operator < (const int b) const {
		return x<b;
	}
} jzm[Size];		//枪毙名单 
inline bool operator < (const int a,const bullet b) {
	return a<b.x;
}
int tot,T[Size],ls[Size*LOG],rs[Size*LOG],sum[Size*LOG];
int update(int pre,int l,int r,int v) {
	int rt=++tot;
	ls[rt]=ls[pre]; rs[rt]=rs[pre];
	sum[rt]=sum[pre]+1;
	if(l<r) {
		int mid=(l+r)>>1;
		if(v<=mid) {
			ls[rt]=update(ls[pre],l,mid,v);
		} else {
			rs[rt]=update(rs[pre],mid+1,r,v);
		}
	}
	return rt;
}
int query(int u,int v,int l,int r,int k) {
	if(l==r)	return l;
	int mid=(l+r)>>1,num=sum[ls[v]]-sum[ls[u]];
	if(k<=num)	return query(ls[u],ls[v],l,mid,k);
	return query(rs[u],rs[v],mid+1,r,k-num);
}
void Fujibayashi_Ryou() {
//	damage[1]=1; damage[2]=3; damage[3]=4; damage[4]=6;
//	printf("%d\n",damage[upper_bound(damage+1,damage+1+4,6)-damage-1]);
	n=read();
	m=read();
	for(re i=1; i<=n; i++) {
		wood[i].x1=read();
		wood[i].x2=read();
		wood[i].s=read();
	}
	for(re i=1; i<=m; i++) {
		jzm[i].x=read();
		jzm[i].t=i;
	}
	sort(jzm+1,jzm+1+m);
	for(re i=1; i<=m; i++) {
		T[i]=update(T[i-1],1,m,jzm[i].t);
	}
	for(re i=1; i<=n; i++) {
		int pre=lower_bound(jzm+1,jzm+1+m,wood[i].x1)-jzm;
		int suf=upper_bound(jzm+1,jzm+1+m,wood[i].x2)-jzm-1;
		if(suf-pre+1<wood[i].s)	continue;
		damage[query(T[pre-1],T[suf],1,m,wood[i].s)]++;
	}
	for(re i=1; i<=m; i++) {
		printf("%d\n",damage[i]);
	}
}
 
}
int main() {
	I_Love::Fujibayashi_Ryou();
	return 0;
}
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值