[LOJ]#2736. 「JOISC 2016 Day 3」回转寿司 分块

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/88322999

Solution

显然每次操作是要选一个上升子序列, 然后把整体往后推,去掉一个最大值,加入 A A ,考虑怎么维护。
看见数据范围和时限,大胆猜测是分块。这里采用一种类似线段树中 l a z y lazy 标记的思想。对于中间的整块,显然是加入 A A 之后出来一个最大值,我们每个块用一个堆维护最大值,暂时不管数的顺序。但是对于左右的不完整块,我们必须知道数的位置,用另外一个堆维护这个块有哪些数经过过,然后当我们需要知道它的位置信息时就把他们拿出来重构,具体方法见代码。
复杂度 O ( n log n n ) O(n\log n\sqrt n)

Code

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=400010;
const int inf=2147483647;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*f;
}
int n,m,k,bel[Maxn],st[Maxn],ed[Maxn],a[Maxn];
priority_queue<int>q1[640];
priority_queue<int,vector<int>,greater<int> >q2[640];
void rebuild(int x)
{
	while(!q1[x].empty())q1[x].pop();
	for(int i=st[x];i<=ed[x];i++)q1[x].push(a[i]);
}
void update(int x)
{
	if(q2[x].empty())return;
	for(int i=st[x];i<=ed[x];i++)
	{
		int v=q2[x].top();
		if(v<a[i])swap(a[i],v),q2[x].pop(),q2[x].push(v);
	}
	while(!q2[x].empty())q2[x].pop();
	rebuild(x);
}
int solve(int l,int r,int A)
{
	if(bel[l]==bel[r])
	{
		update(bel[l]);
		for(int i=l;i<=r;i++)
		if(A<a[i])swap(A,a[i]);
		rebuild(bel[l]);
	}
	else
	{
		update(bel[l]);
		for(int i=l;i<=ed[bel[l]];i++)
		if(A<a[i])swap(A,a[i]);
		rebuild(bel[l]);
		for(int i=bel[l]+1;i<bel[r];i++)
		{
			if(q1[i].top()<=A)continue;
			int nA=q1[i].top();q1[i].pop();
			q1[i].push(A);q2[i].push(A);
			A=nA;
		}
		update(bel[r]);
		for(int i=st[bel[r]];i<=r;i++)
		if(A<a[i])swap(A,a[i]);
		rebuild(bel[r]);
	}
	return A;
}
int main()
{
	n=read(),m=read();k=(int)sqrt(n);
	for(int i=1;i<=n;i++)
	{
		bel[i]=(i-1)/k+1,q1[bel[i]].push(a[i]=read());
		ed[bel[i]]=i;if(!st[bel[i]])st[bel[i]]=i;
	}
	while(m--)
	{
		int l=read(),r=read(),A=read();
		if(l<=r)printf("%d\n",solve(l,r,A));
		else printf("%d\n",solve(1,r,solve(l,n,A)));
	}
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/88322999