ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【瞎口胡】整体二分

2021-09-11 19:31:51  阅读:163  来源: 互联网

标签:二分 递归 int 陨石雨 瞎口 整体 mid leq need


整体二分是处理多个相似询问的利器。

例题 [POI2011]MET-Meteors

题意

有一个 \(n\) 个节点的环,每个节点都有一个所属国家。共有 \(n\) 个国家,第 \(i\) 个国家的陨石需求量为 \(p_i\)。

现在有 \(k\) 场陨石雨,每次陨石雨会落在 \([l,r]\) 区间内每一个节点上,并使这些节点的陨石数量增加 \(a\)。

询问每个国家至少在第几次陨石雨之后才能达到需求量,或者指出这不可能。

\(1 \leq n,m ,k \leq 3 \times 10^5,1 \leq p_i,a_i \leq 10^9\)

题解

先考虑一个询问是怎么样的。直接二分:如果 \([l,mid]\) 的陨石雨落下来之后达到了需求量,那答案一定 \(\leq mid\),清除 \([l,mid]\) 的陨石雨并递归 \([l,mid]\);否则不清除,递归 \([mid+1,r]\)。

\(n\) 个询问也是一样的。二分,把 \([l,mid]\) 的陨石雨落下来之后可以达到需求量的询问往 \([l,mid]\) 递归,反之往 \([mid+1,r]\) 递归。

因为最多递归 \(\log\) 次,所以复杂度是 \(O(n \log^2 n)\) 的(\(n,m,k\) 同阶,时间复杂度均以 \(n\) 表示)。

# include <bits/stdc++.h>
# define int long long
const int N=300010,INF=0x3f3f3f3f;

struct Node{
	int l,r,val,id;
}a[N<<1];
int opsum;
std::vector <int> idx[N];

int n,m,k;

int sum[N],need[N];
int q1[N],q2[N],q[N],ans[N];
inline int read(void){
	int res,f=1;
	char c;
	while((c=getchar())<'0'||c>'9')
		if(c=='-')f=-1;
	res=c-48;
	while((c=getchar())>='0'&&c<='9')
		res=res*10+c-48;
	return res*f;
}
inline int lowbit(int x){
	return x&(-x);
}
inline void add(int x,int v){
	for(;x<=m;x+=lowbit(x))
		sum[x]+=v;
	return;
}
inline int query(int x){
	int ans=0;
	for(;x;x-=lowbit(x))
		ans+=sum[x];
	return ans;
}
inline int getsum(int x){
	int ans=0;
	for(int i=0;i<(int)idx[x].size();++i){
		ans+=query(idx[x][i]);
		if(ans>=need[x])
			return ans;
	}
	return ans;
}
void calc(int l,int r,int L,int R){
	if(L>R)
		return;	
		
	if(l==r){
		for(int i=L;i<=R;++i)
			ans[q[i]]=a[l].id;
		return;
	}
	int mid=(l+r)>>1;
	for(int i=l;i<=mid;++i)
		add(a[i].l,a[i].val),add(a[i].r+1,-a[i].val);

	int pL=0,pR=0;
	for(int i=L;i<=R;++i){
		int now=getsum(q[i]);
		if(now>=need[q[i]])
			q1[++pL]=q[i];
		else
			q2[++pR]=q[i],need[q[i]]-=now;
	}
	for(int i=1;i<=pL;++i)
		q[L+i-1]=q1[i];
	for(int i=1;i<=pR;++i)
		q[L+pL+i-1]=q2[i];
	for(int i=l;i<=mid;++i)
		add(a[i].l,-a[i].val),add(a[i].r+1,a[i].val);
	calc(l,mid,L,L+pL-1),calc(mid+1,r,L+pL,R);
	return;
}
signed main(void){
	n=read(),m=read();
	for(int i=1;i<=m;++i)
		idx[read()].push_back(i);
	for(int i=1;i<=n;++i)
		need[i]=read(),q[i]=i;
	k=read();
	for(int i=1;i<=k;++i){
		int l=read(),r=read(),val=read();
		if(l<=r){
			a[++opsum].l=l,a[opsum].r=r,a[opsum].val=val,a[opsum].id=i;
		}else{
			a[++opsum].l=l,a[opsum].r=m,a[opsum].val=val,a[opsum].id=i;
			a[++opsum].l=1,a[opsum].r=r,a[opsum].val=val,a[opsum].id=i; // 环形可以拆成两个
		}
	}	
	a[++opsum].l=1,a[opsum].r=m,a[opsum].id=k+1,a[opsum].val=1e9;
	calc(1,opsum,1,n);

	for(int i=1;i<=n;++i)
		if(ans[i]==k+1)
			puts("NIE");
		else
			printf("%lld\n",ans[i]);
	return 0;
}

标签:二分,递归,int,陨石雨,瞎口,整体,mid,leq,need
来源: https://www.cnblogs.com/liuzongxin/p/15256553.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有