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

题目大意:给定一个环,每个节点有一个所属国家,k次事件,每次对[l,r]区间上的每个点点权加上一个值,求每个国家最早多少次操作之后所有点的点权和能达到一个值

首先我们考虑暴力想法

对于每个国家分开讨论 二分操作次数

但是这样每次Judge的时候我们要模拟1~mid所有的操作 浪费在这里的复杂度实在太大

这样做每个国家需要模拟O(klogk)次操作 时间复杂度O(nklogk) TLE

我们需要对浪费在这里的复杂度做一些改进

1.可持久化线段树(MLE)

每次二分一个mid之后 我们要找到mid次操作之后的版本

那么很容易想到可持久化线段树

这样每次二分到一个mid可以O(logm)得到值 时间复杂度O(klogm+nlogklogm)

残念的是我MLE了- - 本来以为写了标记永久化的线段树能省掉不少空间的- - 结果- -

内存池就算开了1500W也不够用 真是卡成狗- -

2.整体二分

不能从k下手,我们就要从n下手

二分Solve(x,y,S)表示答案落在[x,y]区间内的国家集合为S

将当前的修改调整至mid,将S集合分为两部分:答案落在[l,mid]的S1和[mid+1,r]的S2

对这两部分继续分治 直到x==y为止 统计答案 退出

时间复杂度O(nlogklogm) 此外注意30W*30W*10E会爆long long 所以我开成了short。。。

代码(整体二分):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
struct Segtree{
	Segtree *ls,*rs;
	double val;
	void* operator new (size_t)
	{
		static Segtree mempool[M<<1],*C=mempool;
		return C++;
	}
	void Build_Tree(int x,int y)
	{
		int mid=x+y>>1;
		if(x==y)
			return ;
		ls=new Segtree;
		rs=new Segtree;
		ls->Build_Tree(x,mid);
		rs->Build_Tree(mid+1,y);
	}
	void Modify(int x,int y,int l,int r,int val)
	{
		int mid=x+y>>1;
		if(x==l&&y==r)
		{
			this->val+=val;
			return ;
		}
		if(r<=mid) ls->Modify(x,mid,l,r,val);
		else if(l>mid) rs->Modify(mid+1,y,l,r,val);
		else ls->Modify(x,mid,l,mid,val),rs->Modify(mid+1,y,mid+1,r,val);
	}
	double Get_Ans(int x,int y,int pos)
	{
		int mid=x+y>>1;
		if(x==y)
			return val;
		if(pos<=mid)
			return val+ls->Get_Ans(x,mid,pos);
		else
			return val+rs->Get_Ans(mid+1,y,pos);
	}
}tree;
struct abcd{
	int pos,next;
}table[M];
struct modification{
	int l,r,p;
}modifications[M];
int head[M],tot;
int n,m,k,now;
int a[M],q[M],ans[M];
void Add(int x,int y)
{
	table[++tot].pos=y;
	table[tot].next=head[x];
	head[x]=tot;
}
void Holistic_Bisection(int x,int y,int l,int r)
{
	static int nq[M];
	int i,mid=x+y>>1;
	if(l>r) return ;
	if(x==y)
	{
		for(i=l;i<=r;i++)
			ans[q[i]]=mid;
		return ;
	}
	while(now<mid)
	{
		++now;
		if(modifications[now].l<=modifications[now].r)
			tree.Modify(1,m,modifications[now].l,modifications[now].r,modifications[now].p);
		else
			tree.Modify(1,m,1,modifications[now].r,modifications[now].p),
			tree.Modify(1,m,modifications[now].l,m,modifications[now].p);
	}
	while(now>mid)
	{
		if(modifications[now].l<=modifications[now].r)
			tree.Modify(1,m,modifications[now].l,modifications[now].r,-modifications[now].p);
		else
			tree.Modify(1,m,1,modifications[now].r,-modifications[now].p),
			tree.Modify(1,m,modifications[now].l,m,-modifications[now].p);
		--now;
	}
	int _l=l,_r=r;
	for(int j=l;j<=r;j++)
	{
		double temp=0;
		for(i=head[q[j]];i;i=table[i].next)
		{
			temp+=tree.Get_Ans(1,m,table[i].pos);
			if(temp>=1000000000)
				temp=1000000000;
		}
		if(temp>=a[q[j]])
			nq[_l++]=q[j];
		else nq[_r--]=q[j];
	}
	memcpy(q+l,nq+l,sizeof(q[0])*(r-l+1) );
	Holistic_Bisection(x,mid,l,_l-1);
	Holistic_Bisection(mid+1,y,_r+1,r);
}
int main()
{
	int i,x;
	cin>>n>>m;
	for(i=1;i<=m;i++)
	{
		scanf("%d",&x);
		Add(x,i);
	}
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	tree.Build_Tree(1,m);
	cin>>k;
	for(i=1;i<=k;i++)
		scanf("%d%d%d",&modifications[i].l,&modifications[i].r,&modifications[i].p);
	for(i=1;i<=n;i++)
		q[i]=i;
	Holistic_Bisection(1,k+1,1,n);
	for(i=1;i<=n;i++)
	{
		if(ans[i]<=k) printf("%d\n",ans[i]);
		else puts("NIE");
	}
	return 0;
}

代码(可持久化线段树):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
typedef long long ll;

struct Segtree{
	Segtree *ls,*rs;
	int val;
	void* operator new (size_t,Segtree *_,Segtree *__,ll ___)
	{
		static Segtree mempool[17500000],*C=mempool;
		C->ls=_;
		C->rs=__;
		C->val=___;
		if(C->val>=1000000000)
			C->val=1000000000;
		return C++;
	}
}*tree[M];
struct abcd{
	int pos,next;
}table[M];
int head[M],tot;
int n,m,k,a[M];
Segtree* Modify(Segtree *p,int x,int y,int l,int r,ll val)
{
	int mid=x+y>>1;
	if(x==l&&y==r)
		return new (p->ls,p->rs,p->val+val) Segtree;
	if(r<=mid)
		return new (Modify(p->ls,x,mid,l,r,val),p->rs,p->val) Segtree;
	if(l>mid) return new (p->ls,Modify(p->rs,mid+1,y,l,r,val),p->val) Segtree;
	return new (Modify(p->ls,x,mid,l,mid,val),Modify(p->rs,mid+1,y,mid+1,r,val),p->val) Segtree;
}
Segtree* Modify(Segtree *p,int x,int y,int l,int r,ll val,bool)
{
	int mid=x+y>>1;
	if(l>mid) return new (new(p->ls->ls,p->ls->rs,p->ls->val+val)Segtree,Modify(p->rs,mid+1,y,l,r,val,true),p->val) Segtree;
	if(r<=mid) return new (Modify(p->ls,x,mid,l,r,val,true),new(p->rs->ls,p->rs->rs,p->rs->val+val)Segtree,p->val) Segtree;
	return new (Modify(p->ls,x,mid,x,l,val),Modify(p->rs,mid+1,y,r,y,val),p->val) Segtree;
}
ll Get_Ans(Segtree *p,int x,int y,int pos)
{
	int mid=x+y>>1;
	if(p==tree[0]) return 0;
	if(x==y) return p->val;
	if(pos<=mid) return p->val+Get_Ans(p->ls,x,mid,pos);
	else return p->val+Get_Ans(p->rs,mid+1,y,pos);
}
void Initialize()
{
	tree[0]=new (0x0,0x0,0) Segtree;
	tree[0]->ls=tree[0]->rs=tree[0];
}
void Add(int x,int y)
{
	table[++tot].pos=y;
	table[tot].next=head[x];
	head[x]=tot;
}
int Bisection(int x)
{
	int i,l=0,r=k+1;
	while(l+1<r)
	{
		int mid=l+r>>1;
		long long now=0;
		for(i=head[x];i;i=table[i].next)
			now+=Get_Ans(tree[mid],1,m,table[i].pos);
		if(now>=a[x])
			r=mid;
		else
			l=mid;
	}
	long long now=0;
	for(i=head[x];i;i=table[i].next)
		now+=Get_Ans(tree[l],1,m,table[i].pos);
	return now>=a[x]?l:r;
}
int main()
{
	int i,x,y,z;
	Initialize();
	cin>>n>>m;
	for(i=1;i<=m;i++)
	{
		scanf("%d",&x);
		Add(x,i);
	}
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	cin>>k;
	for(i=1;i<=k;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		if(x<=y) tree[i]=Modify(tree[i-1],1,m,x,y,z);
		else tree[i]=Modify(tree[i-1],1,m,y,x,z,true);
	}
	for(i=1;i<=n;i++)
	{
		int temp=Bisection(i);
		if(temp==k+1) puts("NIE");
		else printf("%d\n",temp);
	}
	return 0;
}
时间: 2024-10-18 09:42:18

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

BZOJ 2527 [Poi2011]Meteors(整体二分)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2527 [题目大意] 有N个成员国.现在它发现了一颗新的星球, 这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况. BIU的第i个成员国希望能够收集Pi单位的陨石样本. 你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. [题解] 如果枚举每场陨石雨,树状数组查询每个

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

题目描述 有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况.BIU的第i个成员国希望能够收集Pi单位的陨石样本.你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. 输入 第一行是两个数N,M. 第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站. 第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量. 第四行有一个

Luogu3527 POI2011 Meteors 整体二分、树状数组、差分

传送门 比较板子的整体二分题目,时限有点紧注意常数 整体二分的过程中将时间在\([l,mid]\)之间的流星使用树状数组+差分进行维护,然后对所有国家查看一遍并分好类,递归下去,记得消除答案在\([mid+1,r]\)的询问中时间在\([l,mid]\)的流星操作的贡献 注意:可能存在某一段时间某一个国家的流星数量超过long long范围,应该当某个时候国家流星量和大于等于国家需求值时直接退出,这样可以避免这个问题. #include<bits/stdc++.h> #define INF 0

【BZOJ-2527】Meteors 整体二分 + 树状数组

2527: [Poi2011]Meteors Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 831  Solved: 306[Submit][Status][Discuss] Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colo

2527: [Poi2011]Meteors

2527: [Poi2011]Meteors Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1528  Solved: 556[Submit][Status][Discuss] Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for col

主席树/函数式线段树/可持久化线段树

什么是主席树 可持久化数据结构(Persistent data structure)就是利用函数式编程的思想使其支持询问历史版本.同时充分利用它们之间的共同数据来减少时间和空间消耗. 因此可持久化线段树也叫函数式线段树又叫主席树. 可持久化数据结构 在算法执行的过程中,会发现在更新一个动态集合时,需要维护其过去的版本.这样的集合称为是可持久的. 实现持久集合的一种方法时每当该集合被修改时,就将其整个的复制下来,但是这种方法会降低执行速度并占用过多的空间. 考虑一个持久集合S. 如图所示,对集合的

主席树 | | 可持久化线段树

可持久化数据结构(Persistent data structure)就是利用函数式编程的思想使其支持询问历史版本.同时充分利用它们之间的共同数据来减少时间和空间消耗. 所以这里讲的可持久化线段树也叫函数式线段树(又叫主席树……因为先驱就是fotile主席Orz……). 先了解一下主席树 http://seter.is-programmer.com/posts/31907.html    很详细的介绍了函数式线段树(主席树). 主席树其实就是很多棵线段树,由于每次更新只需要更新logN个节点,所

【bzoj4212】神牛的养成计划 Trie树+可持久化Trie树

题目描述 Hzwer成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变,原先决定神牛特征的基因序列都被破坏了,神牛hzwer很生气,但他知道基因突变的低频性,说不定还有以下优秀基因没有突变,那么他就可以用限制性核酸内切酶把它们切出来,然后再构建基因表达载体什么的,后面你懂的...... 黄学长现在知道了N个细胞的DNA序列,它们是若干个由小写字母组成的字符串.一个优秀的基因是两个字符串s1和s2,当且仅当s1是某序列

bzoj 2527 Meteors - 整体二分 - 树状数组

Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of st