【BZOJ2527】【POI2011】Meteors(整体二分)

本文详细解析了整体二分算法的实现过程,通过记录每个国家拥有的空间站,使用二分查找来优化搜索效率。文章提供了完整的代码示例,包括数据结构定义、更新和查询操作,以及如何解决特定问题的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

很简单的整体二分
对每个国家记录一下有哪些空间站
注意极限数据一个国家收集到的数量可能会炸 l o n g   l o n g long\ long long long
中途判断是否已经满足 b r e a k break break就可以了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
	return res*f;
} 
const int N=300005;
const ll inf=1e12;
struct ctry{
	vector<int>son;
	ll hop;int id;
}p[N],p1[N],p2[N];
struct rain{
	int l,r;ll a;
}q[N];
int n,m,k,ans[N];
inline int lowbit(int x){
	return x&(-x);
}
ll tr[N];
inline void modify(int p,ll k){
	for(;p<=m;p+=lowbit(p))tr[p]+=k;
}
inline void update(int l,int r,ll k){
	modify(l,k),modify(r+1,-k);
}
inline ll query(int p,ll res=0){
	for(;p;p-=lowbit(p))res+=tr[p];return res;
}
void solve(int l,int r,int st,int des){
	if(l==r){
		for(int i=st;i<=des;i++)ans[p[i].id]=l;return;
	}
	int mid=(l+r)>>1,cnt1=0,cnt2=0;
	for(int i=l;i<=mid;i++){
		if(q[i].l<=q[i].r){
			update(q[i].l,q[i].r,q[i].a);
		}
		else update(q[i].l,m,q[i].a),update(1,q[i].r,q[i].a);
	}
	for(int i=st;i<=des;i++){
		ll res=0;
		for(int j=0;j<p[i].son.size();j++){
			res+=query(p[i].son[j]);
			if(res>=p[i].hop)break;
		}
		if(res<p[i].hop)p[i].hop-=res,p2[++cnt2]=p[i];
		else p1[++cnt1]=p[i];
	}
	for(int i=1;i<=cnt1;i++)p[st+i-1]=p1[i];
	for(int i=1;i<=cnt2;i++)p[st+cnt1+i-1]=p2[i];
	for(int i=l;i<=mid;i++){
		if(q[i].l<=q[i].r){
			update(q[i].l,q[i].r,-q[i].a);
		}
		else update(q[i].l,m,-q[i].a),update(1,q[i].r,-q[i].a);
	}
	solve(l,mid,st,st+cnt1-1),solve(mid+1,r,st+cnt1,des);
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		p[read()].son.push_back(i);
	}
	for(int i=1;i<=n;i++){
		p[i].hop=read(),p[i].id=i;
	}
	k=read();
	for(int i=1;i<=k;i++){
		q[i].l=read(),q[i].r=read(),q[i].a=read();
	}
	q[++k].l=1,q[k].r=m,q[k].a=inf;
	solve(1,k,1,n);
	for(int i=1;i<=n;i++){
		if(ans[i]==k)puts("NIE");
		else cout<<ans[i]<<'\n';
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值