【洛谷P3889】吃

题目

题目链接:https://www.luogu.com.cn/problem/P3889
W师兄计划了很久,终于成功的在BG开了一家寿司店。
正当W师兄还在兴奋的时候,这时一个噩耗传来,吃货L师姐居然知道了这件事,而且正赶过来,W师兄瞬间心就冷了下去,但是机智的W师兄也瞬间想到了应付L师姐的策略.......
这时,L师姐到了寿司店,先四处望了望风景,发现现在只有L师姐一个顾客,下面是L师姐的选餐说明:

  1. 寿司店内的寿司被排在一行共N个盘子里,按从左到右编号为\(1\sim N\)
  2. 每个位置上寿司的数量是确定的并且有玻璃窗保护。
  3. 每隔一段时间就会有一个选餐时间,L师姐可以在一个连续的区间\([l,r]\)中选择其中一盘,然后在该区间之外选择另一盘(如果区间外有盘子)。

L师姐发现这家寿司店厨师的制作速度很快,总能在下一次选餐时间前将寿司数量恢复原样。
作为有尊严有追求的吃货,L师姐也有自己的规则,L师姐在选完两盘寿司后,会决定每口恰好吃\(D\)个寿司,且使得两盘寿司刚好可以分别吃完,不剩余任何寿司。比如两盘寿司数量为2和4,那么\(D=1\)或者\(D=2\)都可以恰好将两盘寿司分别吃干净,而两盘寿司数量为3和5时,那么只能\(D=1\)才行。
作为有特殊追求的L师姐才不在乎吃的数量,L师姐在乎的是一口吃多个寿司的感觉。于是,如果L师姐可以一口吃\(D\)个寿司,那么L师姐的愉悦值为\(D\),但是L师姐没有选到两盘寿司,那么她的愉悦值为0。
现在L师姐知道每个盘子所放着的寿司数量,L师姐想知道每次选择时间过后她可以获得的最大愉悦值是多少?

思路

等价于每次给出一个区间\([l,r]\),在\([l,r]\)中取一个数\(x\),在\([1,l)∪(r,n]\)中取一个数\(y\),使得\(gcd(x,y)最大\)

考虑将每次询问拆分成\([1,l)\)\((r,n]\)两部分分别取一个数\(y\),然后在再\(gcd(x,y_1)\)\(gcd(x,y_2)\)中取一个最大值,这样就只要做半(???)个问题。
记录每一个数的因子\(fac[x][...]\),考虑离线解决。
将询问以\(l\)为关键字从小到大排序,那么从一个询问\([l_1,r_1]\)转移到\([l_2,r_2](l_1\leq l_2)\)时,我们只需要处理出\([l_1,l_2)\)对后面的贡献。
对于\(x\in [l_1,l_2)\),假设\(x\)的一个因子为\(p\),在\(x\)的后面还有若干个数字\(x_1,x_2...\)也含有因子\(p\)。其实我们只关心距离\(x\)最近的一个数字\(x_1\),记录对它的贡献即可。因为对于\(x_2\)的贡献可以在枚举到\(x_1\)时计算。
开一棵线段树,在离线处理每一个询问时,线段树一个节点\([l,r]\)表示\([l,r]\)中的数字与离线处理到的位置前的数字的最大\(gcd\)(我在写什么啊
所以我们设\(nxt[x][i]\)表示序列中下一个含有\(fac[x][i]\)的数的位置。那么当我们枚举到数字\(x\)时,我们便利它的每一个因子,将线段树中\(nxt[x][i]\)\(maxgcd\)在原来的\(maxgcd\)\(fac[x][i]\)中取最大值。然后对于这个询问的答案就是询问区间的\(maxgcd\)
这样就搞定了半个问题,对于另外半个问题,我们把序列、因数、询问等全部颠倒过来做一遍就可以了。然后在两个答案中取\(max\)
数字\(x\)的因数上限是\(2\sqrt{x}\),如果直接开这么大的数组空间会炸,考虑到很多数字的因数个数远远达不到上限,\(nxt\)\(fac\)就用\(vector\)省空间即可。
时间复杂度\(O(n\log n+n\sqrt{n})\)
我自己都不知道在写什么,看代码吧(

代码

#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=100010;
int n,m,a[N],ans[N],last[N];
vector<int> fac[N],nxt[N];

inline int read()
{
	int d=0; char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
	return d;
}

struct ASK
{
	int l,r,id;
}ask[N];

struct Treenode
{
	int l,r,maxgcd;
};

struct TREE
{
	Treenode tree[N*4];
	
	inline void build(int x,int l,int r)
	{
		tree[x].l=l; tree[x].r=r; tree[x].maxgcd=0;
		if (l==r) return;
		int mid=(l+r)>>1;
		build(x*2,l,mid);
		build(x*2+1,mid+1,r);
	}
	
	inline void update(int x,int k,int val)
	{
		if (tree[x].l==k && tree[x].r==k)
		{
			tree[x].maxgcd=max(tree[x].maxgcd,val);
			return;
		}
		int mid=(tree[x].l+tree[x].r)>>1;
		if (k<=mid) update(x*2,k,val);
			else update(x*2+1,k,val);
		tree[x].maxgcd=max(tree[x*2].maxgcd,tree[x*2+1].maxgcd);
	}
	
	inline int ask(int x,int l,int r)
	{
		if (tree[x].l==l && tree[x].r==r)
			return tree[x].maxgcd;
		int mid=(tree[x].l+tree[x].r)>>1;
		if (r<=mid) return ask(x*2,l,r);
		else if (l>mid) return ask(x*2+1,l,r);
		else return max(ask(x*2,l,mid),ask(x*2+1,mid+1,r));
	}
}Tree;

inline bool cmp(ASK x,ASK y)
{
	return x.l<y.l;
}

inline void solve()
{
	for (register int i=1;i<=n;i++)
		nxt[i].clear();
	Tree.build(1,1,n);
	memset(last,0,sizeof(last));
	for (register int i=n;i>=1;i--)
		for (register int j=0;j<fac[i].size();j++)
		{
			nxt[i].push_back(last[fac[i][j]]);
			last[fac[i][j]]=i;
		}
	sort(ask+1,ask+1+m,cmp);
	for (register int i=1,j=1;i<=m;i++)
	{
		for (;j<ask[i].l;j++)
			for (register int k=0;k<nxt[j].size();k++)
				if (nxt[j][k]) Tree.update(1,nxt[j][k],fac[j][k]);
		ans[ask[i].id]=max(ans[ask[i].id],Tree.ask(1,ask[i].l,ask[i].r));
	}
}

int main()
{
	n=read();
	for (register int i=1;i<=n;i++)
	{
		a[i]=read();
		for (register int j=1;j*j<=a[i];j++)
			if (!(a[i]%j))
			{
				fac[i].push_back(j);
				if (a[i]/j!=j) fac[i].push_back(a[i]/j);
			}
	}
	m=read();
	for (register int i=1;i<=m;i++)
	{
		ask[i].l=read(); ask[i].r=read();
		ask[i].id=i;
	}
	solve();
	for (register int i=1;i<=n/2;i++)  //颠倒
	{
		swap(a[i],a[n-i+1]);
		fac[i].swap(fac[n-i+1]);
	}
	for (register int i=1;i<=m;i++)
	{
		swap(ask[i].l,ask[i].r);
		ask[i].l=n-ask[i].l+1;
		ask[i].r=n-ask[i].r+1;
	}
	solve();
	for (register int i=1;i<=m;i++)
		printf("%d\n",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/stoorz/p/12215316.html