关闭

bzoj2527[Poi2011] Meteors

标签: 整体二分
506人阅读 评论(0) 收藏 举报
分类:

题目链接:bzoj2527

题目大意:

相当于,有n个人,m个数,每个数分别累加到一个人身上,所以一个人的值等于所有归他的数的和。这m个数按顺序排一个。有k个操作,每个操作则给[l,r]上的数都增加ai,而每个人都有个目标pi。问对于每个人来说,第几个操作后,他的值达到了他的目标。【诶差不多这个意思

数据范围:1<=n,m,k<=300000


题解:

转自http://victorwonder.is-programmer.com/posts/70210.html

首先,我们需要用一个列表id[]记录所有查询的编号,刚开始的时候,id[]自然是递增的.同时,我们用一个数组cur[i]记录下,第i个国家在l-1场流星雨过后,收集到的陨石的数目。
主过程为void solve(int head,int tail,int l,int r),表示对于id[head]到id[tail]的所有询问,在[l,r]范围内查询答案,通过上一层的操作,我们保证id[head]到id[tail]的所有询问的答案都在[l,r]范围内。
首先,我们先模拟[l,mid]这么多次操作(在询问重新划分之后,必须要再次模拟,将数组清空),用树状数组或者是线段树计算出在[l,mid]场流星雨之后,每个空间站收集到的陨石的数目。
然后我们查询,每个国家收集到的陨石的数目,要注意的是,我们需要用链表储存每个国家对应的空间站,并且一一枚举,用tmp[id[i]]表示国家id[i]收集到的陨石的数目。
那么从[1,mid]这么多次操作之后,国家id[i]收集到的陨石数目就是tmp[id[i]]+cur[id[i]],如果tmp[id[i]]+cur[id[i]]>p[id[i]],那么表明对于国家id[i],其答案在[l,mid]这个范围内,否则其答案在[mid+1,r]范围内,并将tmp[id[i]]累加到cur[id[i]]上。
还有一个坑点是,tmp[id[i]]可能很大,会爆掉long long,所以如果枚举一个国家的所有空间站的时候,发现tmp[id[i]]已经大于p[id[i]]了,那么就break好了,不然会出错。
因为可能会出现怎么也无法满足的情况,所以我们需要多增加一场流星雨,这场流星雨的数量为infi,保证能够让所有国家都满足要求,那么最后,对于所有答案为k+1的询问,输出NIE就行了。
 
总的来说,整体二分就是将所有询问一起二分,然后获得每个询问的答案。

这篇写得真的很好(很容易懂)!我的第一道整体二分!模板什么的就是学他的。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 0x7fffffff
#define maxn 310000
typedef long long LL;

struct question
{
	int l,r;LL c;
}q[maxn];
int m,len,nxt[maxn],first[maxn];
LL c[maxn],sd[maxn],cur[maxn],tmp[maxn];
int ans[maxn],tol[maxn],tor[maxn],id[maxn],to[maxn];
void ins(int x,int y)
{
	to[++len]=y;
	nxt[len]=first[x];
	first[x]=len;
}
int lowbit(int x){return x&(-x);}
void change(int x,LL k)
{
	for (x;x<=m;x+=lowbit(x)) c[x]+=k;
}
LL query(int x)
{
	LL ret=0;
	for (x;x>0;x-=lowbit(x)) ret+=c[x];
	return ret;
}
void modify(int x,int y,LL z)
{
	change(x,z);
	change(y+1,-z);
}
void solve(int head,int tail,int l,int r)
{
	int i,lnum=0,rnum=0;
	int mid=(l+r)>>1;
	if (l==r)
	{
		for (i=head;i<=tail;i++) ans[id[i]]=l;
		return;
	}
	for (i=l;i<=mid;i++)
	{
		if (q[i].l<=q[i].r) modify(q[i].l,q[i].r,q[i].c);
		else modify(q[i].l,m,q[i].c),modify(1,q[i].r,q[i].c);
	}
	for (i=head;i<=tail;i++)
	{
		tmp[id[i]]=0;
		for (int k=first[id[i]];k!=-1;k=nxt[k])
		{
			LL now=query(to[k]);
			tmp[id[i]]+=now;
			if (tmp[id[i]]+cur[id[i]]>sd[id[i]]) break;
		}
		if (tmp[id[i]]+cur[id[i]]>=sd[id[i]]) tol[++lnum]=id[i];
		else {tor[++rnum]=id[i];cur[id[i]]+=tmp[id[i]];}
	}
	for (i=l;i<=mid;i++)
	{
		if (q[i].l<=q[i].r) modify(q[i].l,q[i].r,-q[i].c);
		else modify(q[i].l,m,-q[i].c),modify(1,q[i].r,-q[i].c);
	}
	for (i=0;i<lnum;i++) id[head+i]=tol[i+1];
	for (i=0;i<rnum;i++) id[head+lnum+i]=tor[i+1];
	solve(head,head+lnum-1,l,mid);
	solve(head+lnum,tail,mid+1,r);
}
int main()
{
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int n,i,x,k;
	scanf("%d%d",&n,&m);len=0;
	memset(c,0,sizeof(c));
	memset(first,-1,sizeof(first));
	for (i=1;i<=m;i++)
	{
		scanf("%d",&x);
		ins(x,i);
	}
	for (i=1;i<=n;i++) {scanf("%d",&sd[i]);id[i]=i;}
	scanf("%d",&k);
	for (i=1;i<=k;i++)
	  scanf("%d%d%lld",&q[i].l,&q[i].r,&q[i].c);
	k++;q[k].l=1;q[k].r=m;q[k].c=inf;
	solve(1,n,1,k);
	for (i=1;i<=n;i++) 
	  if (ans[i]!=k) printf("%d\n",ans[i]);
	  else printf("NIE\n");
	return 0;
}



0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

【bzoj2527】Meteors【整体二分】

有n个国家和m个空间站,每个空间站都属于一个国家,一个国家可以有多个空间站,所有空间站按照顺序形成一个环,也就是说,m号空间站和1号空间站相邻。 现在,将会有k场流星雨降临,每一场流星雨都会给区间[...
  • ZMOIYNLP
  • ZMOIYNLP
  • 2015-05-12 11:08
  • 1644

BZOJ 2527 Poi2011 Meteors 整体二分+线段树 / 可持久化线段树(MLE)

题目大意:给定一个环,每个节点有一个所属国家,k次事件,每次对[l,r]区间上的每个点点权加上一个值,求每个国家最早多少次操作之后所有点的点权和能达到一个值 首先我们考虑暴力想法 对于每个国家分开讨论...
  • PoPoQQQ
  • PoPoQQQ
  • 2014-12-30 10:56
  • 1624

BZOJ 2280 Poi2011 Plot 二分答案+随机增量法

题目大意:给定n个点,要求分成m段,使每段最小覆盖圆半径的最大值最小 二分答案,然后验证的时候把点一个个塞进最小覆盖圆中,若半径超了就分成一块…… 等等你在跟我说不随机化的随机增量法? 好吧 ...
  • PoPoQQQ
  • PoPoQQQ
  • 2015-04-17 19:14
  • 1581

BZOJ 2527 [Poi2011]Meteors [整体二分+线段树]

BZOJ 2527 [Poi2011]Meteors [整体二分+线段树]
  • ACTerminate
  • ACTerminate
  • 2017-07-11 20:06
  • 196

[BZOJ2527][Poi2011][整体二分][树状数组]Meteors

整体二分区间[l,r]为当前处理修改操作区间,即陨石雨的区间,[L,R]为询问操作区间,即每个国家,那么执行[l,r]区间的修改,对于[L,R]中的每个国家,用树状数组查询收集到的陨石,如果大于希望获...
  • Coldef
  • Coldef
  • 2017-02-17 22:42
  • 181

bzoj2527 [Poi2011]Meteors(整体二分+树状数组)

bzoj2527 [Poi2011]Meteors 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2527 题意: Byteotian...
  • Bfk_zr
  • Bfk_zr
  • 2018-01-09 10:09
  • 38

【BZOJ】2527 [Poi2011]Meteors 整体二分+树状数组

题目传送门 这题的整体二分还是挺好想到的,代码也挺好写的。(比BZOJ3110好写多……) 取当期的陨石波数的一半加入树状数组中,判断当前每个国家拥有的陨石数是否达到需求量,若达到则放到左区间中,也就...
  • lyfsb
  • lyfsb
  • 2017-07-11 09:43
  • 151

BZOJ 2527: [Poi2011]Meteors 整体二分

题目大意:给定一个环,环上每个位置有一个国家的基地,每次流星雨会让一段区间每个收获到一个数值的收益,给定每个国家的需要收益总数,求出每个国家最早在第几次流星雨之后能获得要求的收益。 题解:这道题有好...
  • LZJ209
  • LZJ209
  • 2017-01-16 21:29
  • 213

整体二分——BZOJ2527/Luogu3527 [POI2011]MET-Meteors

题面:洛谷3527 BZOJ2527 这题首先可以想到二分答案但是呢有很多点需要二分 同时每个点的二分状态都差不多 那么我们就一起二分(整体二分) 每次二分出答案以后对于每个国家计算有几颗流星...
  • jzq233jzq
  • jzq233jzq
  • 2017-05-02 11:30
  • 206

bzoj2527 [Poi2011]Meteors(整体二分+树状数组)

DescriptionByteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galax...
  • wu_tongtong
  • wu_tongtong
  • 2017-12-17 21:18
  • 69
    个人资料
    • 访问:64577次
    • 积分:2599
    • 等级:
    • 排名:第16176名
    • 原创:200篇
    • 转载:0篇
    • 译文:0篇
    • 评论:30条
    最新评论