首页 > 其他分享 >P4168 [Violet] 蒲公英(题解)

P4168 [Violet] 蒲公英(题解)

时间:2024-04-19 15:24:44浏览次数:19  
标签:maxx ch int 题解 Violet mark vis ans P4168

题目

题目描述

输入格式

输出格式

数据范围

![]

样例

输入:
6 3 
1 2 3 2 1 2 
1 5 
3 6 
1 5 

输出:
1 
2 
1

思路

暴力

本题求区间内的最小众数,容易想到去用数组sum[i]表示第i种花的个数,在去便利比较,但是复杂度nm一定会T,这时候就要对暴力进行优化。

分块优化1

如果我们将所给数列进行分块,记录sum[i][j]每一块中的每一种花的数量,在进行比较,这样在询问的时候就可以少便利中间整块的花,而只便利两边的残缺块即可,但这样仍然会T。
这时候就可以更改sum[i][j]的含义为前i个块中j这一种花的个数。从而减小整块的花的询问复杂度。

代码时间

这个代码是可以过掉 洛谷,acwing(我只在这两个网站(除了hjoi)上交了)的。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int maxx=4e4+10;
const int maxn=210;

int cnt,n,m,ans,res;
int belong[maxx],mark[maxx],vis[maxx];
int st[maxn],ed[maxn];
int sum[maxn][maxx];

struct floures
{
	int sp,b,id;
}a[maxx];

int read()
{
	int ans=0;bool f=0;char ch=getchar();
	while(ch<'0' || ch>'9'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0' && ch<='9'){ans=(ans<<1)+(ans<<3)+(ch^48);ch=getchar();}
	return f?~ans+1:ans;
}

void manba_out(int x)
{
	if(x<0){manba_out('-');x=-x;}
    if(x>9)manba_out(x/10);
    putchar(x%10+'0');
}

bool cmp(floures x,floures y)
{
	return x.sp<y.sp;
}

bool cmpp(floures x,floures y)
{
	return x.id<y.id;
}

inline void lsh()
{
	sort(a+1,a+1+n,cmp);
	a[1].b=++res;
	vis[a[1].b]=a[1].sp;
	for(register int i=2;i<=n;i++)
	{
		if(a[i].sp==a[i-1].sp)a[i].b=a[i-1].b;
		else a[i].b=++res;
		vis[res]=a[i].sp;
	}
	sort(a+1,a+1+n,cmpp);
}

inline void prepare()
{
	cnt=(int)sqrt(n);
	for(register int i=1;i<=cnt;i++)
	{
		st[i]=(i-1)*cnt+1;
		ed[i]=i*cnt;
	}
	if(ed[cnt]<n)
	{
		cnt++;
		st[cnt]=ed[cnt-1]+1;
		ed[cnt]=n;
	}
	for(register int i=1;i<=cnt;i++)
	{
		for(register int j=st[i];j<=ed[i];j++)
		{
			belong[j]=i;
			sum[i][a[j].b]++;
		}
		for(register int j=1;j<=res;j++)
		{
			sum[i][j]+=sum[i-1][j];
		}
	}
}

inline int query(int l,int r)
{	
	int ans=0,cut=0;
	memset(mark,0,sizeof mark);
	if(belong[l]==belong[r])
	{
		for(register int i=l;i<=r;i++)
		{
			mark[a[i].b]++;
		}
		cut=mark[1];
		ans=vis[1];
		for(register int i=2;i<=res;i++)
		{
			if(mark[i]>cut)
			{
				cut=mark[i];
				ans=vis[i];
			}
		}
		return ans;
	}
	for(register int i=l;i<=ed[belong[l]];i++)
	{
		mark[a[i].b]++;
	}
	for(register int i=st[belong[r]];i<=r;i++)
	{
		mark[a[i].b]++;
	}
	if(belong[r]-1>belong[l])
	{
		for(register int i=1;i<=res;i++)
		{
			mark[i]+=(sum[belong[r]-1][i]-sum[belong[l]][i]);
			if(mark[i]>cut)
			{
				cut=mark[i];
				ans=vis[i];
			}
		}
	}
	else
	{
		for(register int i=1;i<=res;i++)
		{
			if(mark[i]>cut)
			{
				cut=mark[i];
				ans=vis[i];
			}
		}
	}
	return ans;
}

int main()
{
	n=read();m=read();
	for(register int i=1;i<=n;i++)
	{
		a[i].sp=read();
		a[i].id=i;
	}
	lsh();
	prepare();
	for(register int i=1;i<=m;i++)
	{
		int x,y;
		x=read();y=read();
		int l=(x+ans-1)%n+1;
		int r=(y+ans-1)%n+1;
		if(l>r)swap(l,r);
		ans=query(l,r);
		manba_out(ans);
		putchar('\n');
	}
	
	
	return 0;
}

分块优化2

上个优化需要去便利花的种类,在极限状态下种类为n,复杂度又成了nm,所以我们可以在记录一个mode[i][j]表示第i个块和第j个块的最小众数,这样就不需要便利颜色了。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int maxx=4e4+10;
const int maxn=210;

int cnt,n,m,man,res;
int belong[maxx],mark[maxx],vis[maxx];
int st[maxn],ed[maxn];
int sum[maxn][maxx],mode[maxn][maxn];

struct floures
{
	int sp,b,id;
}a[maxx];

int manba_in()
{
	int ans=0;bool f=0;char ch=getchar();
	while(ch<'0' || ch>'9'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0' && ch<='9'){ans=(ans<<1)+(ans<<3)+(ch^48);ch=getchar();}
	return f?~ans+1:ans;
}

void manba_out(int x)
{
	if(x<0){manba_out('-');x=-x;}
    if(x>9)manba_out(x/10);
    putchar(x%10+'0');
}

bool cmp(floures x,floures y)
{
	return x.sp<y.sp;
}

bool cmpp(floures x,floures y)
{
	return x.id<y.id;
}

inline void memset_mark_0(int l,int r)
{
	for(register int i=l;i<=ed[belong[l]];i++)
	{
		mark[a[i].b]=0;
	}
	for(register int i=st[belong[r]];i<=r;i++)
	{
		mark[a[i].b]=0;
	}
}

inline void lsh()
{
	sort(a+1,a+1+n,cmp);
	a[1].b=++res;
	vis[a[1].b]=a[1].sp;
	for(register int i=2;i<=n;i++)
	{
		if(a[i].sp==a[i-1].sp)a[i].b=a[i-1].b;
		else a[i].b=++res;
		vis[res]=a[i].sp;
	}
	sort(a+1,a+1+n,cmpp);
}

inline void prepare()
{
	cnt=(int)sqrt(n);
	for(register int i=1;i<=cnt;i++)
	{
		st[i]=(i-1)*cnt+1;
		ed[i]=i*cnt;
	}
	if(ed[cnt]<n)
	{
		cnt++;
		st[cnt]=ed[cnt-1]+1;
		ed[cnt]=n;
	}
	for(register int i=1;i<=cnt;i++)
	{
		for(register int j=st[i];j<=ed[i];j++)
		{
			belong[j]=i;
			sum[i][a[j].b]++;
		}
		for(register int j=1;j<=res;j++)
		{
			sum[i][j]+=sum[i-1][j];
		}
	}
	for(register int i=1;i<=cnt;i++)
	{
		int op,num,opn;
		for(register int j=i;j<=cnt;j++)
		{
			op=mode[i][j-1];
			for(register int k=st[j];k<=ed[j];k++)
			{
				opn=sum[j][op]-sum[i-1][op];
				num=sum[j][a[k].b]-sum[i-1][a[k].b];
				if((num>opn)||(num==opn&&vis[op]>vis[a[k].b]))
				{
					op=a[k].b;
				}
			}	
			mode[i][j]=op;
		}
	}
}

inline int query(int l,int r)
{	
	int ans=0,cut=0,val=0;
	if(belong[l]==belong[r])
	{
		for(register int i=l;i<=r;i++)
		{
			mark[a[i].b]++;
			if((mark[a[i].b]>cut)||(mark[a[i].b]==cut&&ans>a[i].b))
			{
				cut=mark[a[i].b];
				ans=a[i].b;
			}
		}
		memset_mark_0(l,r);
		return vis[ans];
	}
	for(register int i=l;i<=ed[belong[l]];i++)
	{
		mark[a[i].b]++;
	}
	for(register int i=st[belong[r]];i<=r;i++)
	{
		mark[a[i].b]++;
	}
	ans=mode[belong[l]+1][belong[r]-1];
	for(register int i=l;i<=ed[belong[l]];i++)
	{
		cut=sum[belong[r]-1][ans]-sum[belong[l]][ans]+mark[ans];
		val=sum[belong[r]-1][a[i].b]-sum[belong[l]][a[i].b];
		if((mark[a[i].b]+val>cut)||(mark[a[i].b]+val==cut&&vis[a[i].b]<vis[ans]))
		{
			ans=a[i].b;
		}
	}
	for(register int i=st[belong[r]];i<=r;i++)
	{
		cut=sum[belong[r]-1][ans]-sum[belong[l]][ans]+mark[ans];
		val=sum[belong[r]-1][a[i].b]-sum[belong[l]][a[i].b];
		if((mark[a[i].b]+val>cut)||(mark[a[i].b]+val==cut&&vis[a[i].b]<vis[ans]))
		{
			ans=a[i].b;
		}
	}
	memset_mark_0(l,r);
	return vis[ans];
}

int main()
{
	n=manba_in();m=manba_in();
	for(register int i=1;i<=n;i++)
	{
		a[i].sp=manba_in();
		a[i].id=i;
	}
	lsh();
	prepare();
	for(register int i=1;i<=m;i++)
	{
		int x,y;
		x=manba_in();y=manba_in();
		int l=(x+man-1)%n+1;
		int r=(y+man-1)%n+1;
		if(l>r)swap(l,r);
		man=query(l,r);
		manba_out(man);
		putchar('\n');
	}
	
	
	return 0;
}

标签:maxx,ch,int,题解,Violet,mark,vis,ans,P4168
From: https://www.cnblogs.com/wang-qa/p/18145937

相关文章

  • Codeforces Round 932 (Div. 2)题解(c、d)
    CodeforcesRound932(Div.2)C.MessengerinMAC题目大意给定一些\(a_i\)\(和b_i\),选出尽量多的\(a_i和b_i\),使得\(\sum_{i=1}^ka_{p_i}+\sum_{i=1}^{k-1}\left|b_{p_i}-b_{p_{i+1}}\right|\)小于给定的\(l\)。题目解析由于题目没有要求\(\{p\}\)是升序排列的序列,因此......
  • P6018 [Ynoi2010] Fusion tree 题解
    题目链接:Fusiontree大部分人貌似用的边权01Trie,实际这题用点权01Trie类似文艺平衡树去写更方便。考虑两种常见的区间维护:线段树。使用的是父节点信息是归并了左右区间的信息,适用于不需要考虑父节点的贡献的信息。文艺平衡树。每个点就是一个信息,归并左右子树,外加当......
  • kafka消息只能在一台服务器消费的问题解决过程
    场景:kafka消费端应用部署在两台机器上,其中一台能消费到生产端发出的kafka消息,另一台服务器接收不到任何消息。解决过程:一、从消费端启动日志中找出所有消费端线程2024-04-2320:04:44,726[xx_xxapp03-1556011171628-976bc2af_watcher_executor]INFOkafka.consumer.RangeA......
  • PKUSC2019 D1T1 题解
    前言五一网课的例题,但是网上没有详细的题解(其实就是都没放代码),所以来写一篇。题目可以在这里提交。题目简述有\(n\)(\(n\leq5\times10^5\))个村庄排成一排,每个村庄里有一个人。第\(i\)个村庄里的人要去第\(p_i\)个村庄,且\(p\)是\(1\simn\)的一个排列。他们出行......
  • [题解]ABC282E Choose Two and Eat One
    ABC282EChooseTwoandEatOne又一个图论的回顾——Kruskal最小(最大)生成树算法。看到\(n\)的范围只有\(500\),应该没有什么特别的算法。那么我们考虑建一个*\(n\)个顶点的完全图,节点\(x\)到节点\(y\)的边权值就是\(x^y+y^x\)。然后跑一遍最大生成树,得到的和就是最大结果了。如......
  • RuntimeError: No CUDA GPUs are available问题解决
    RuntimeError:NoCUDAGPUsareavailable问题解决检查GPU是否可用importtorchiftorch.cuda.is_available():print("GPU可用")else:print("GPU不可用")显示当前可用的GPU数量importtorchprint("当前可用的GPU数量:",torch.cuda.device_count())P......
  • [题解]CF33C Wonderful Randomized Sum
    CF33CWonderfulRandomizedSum我们可以发现,如果两区间不交叉也不会影响到结果,所以我们只需要考虑不交叉的情况即可。我们所选择的前缀\(1\simi\)应满足区间和最小,后缀也一样。所以用两个数组\(lr,rl\)分别记录下\(1\simi\)(前缀)最小和、\(i\simn\)(后缀)最小和。然后枚举分割......
  • 问题解析
    查看内存总量[root@localhost~]#free-h----人性化显示内存使用情况totalusedfreesharedbuff/cacheavailableMem:1.8G329M270M9.1M1.2G1.2GSwap:4.0G0B......
  • [ABC240E] Ranges on Tree 题解
    [ABC240E]RangesonTree题解思路解析由题意可知,只要一个点的所有儿子节点都被确定了,那么当前节点也就被确定了。也就是说,只要确定了所有叶子节点,也就能一层层地确定所有节点,而叶子节点没有儿子节点不受此条件的约束,同时我们希望\(\max\limits^N_{i=1}R_i\)最小,所以我们把所......
  • 【面试准备】跨域问题解决方法
    跨域是什么浏览器对于javascript的同源策略的限制,是一种安全策略举例:用户登陆某个网站后,服务器在客户端写了一些cookie,如果cookie被其他网站读取,那么隐私信息就会泄漏,包含用户的登录状态等。跨域情况说明:域名不同域名相同,端口不同二级域名不同跨域问题解决jsonpngi......