Luogu4168 [Violet]蒲公英
Posted wifimonster
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu4168 [Violet]蒲公英相关的知识,希望对你有一定的参考价值。
题面:https://www.luogu.org/problemnew/show/P4168
首先离散化;
考虑分块,记录信息:
cnt[i][j]表示前i个块元素j出现的次数
f[x][y] 表示块x到块y的众数
g[x][y] 表示块x到块y的众数出现的次数
这三个信息可以预处理
查询答案:
答案属于{中间块的众数}∪{左右两边块中出现的数} (!!!)
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+4; int n,blo,bel[maxn],num[maxn],cnt[204][maxn],a[maxn],val[maxn],f[204][204],g[204][204]; struct node{ int val,pos; }t[maxn]; bool operator < (const node &x,const node &y){ return x.val<y.val; } inline int query(int l,int r){ int ans=f[bel[l]+1][bel[r]-1]; int mx=g[bel[l]+1][bel[r]-1]; memset(num,0,sizeof(num)); for(int i=l;i<=min(bel[l]*blo,r);i++) num[a[i]]++; for(int i=max(l,(bel[r]-1)*blo+1);i<=r;i++) num[a[i]]++; int tmp=0; for(int i=l;i<=min(bel[l]*blo,r);i++){ if(bel[l]==bel[r]){ tmp=num[a[i]]; }else{ tmp=num[a[i]]+cnt[bel[r]-1][a[i]]-cnt[bel[l]][a[i]]; } if(tmp>mx||(tmp==mx&&a[i]<ans)) ans=a[i],mx=tmp; } for(int i=max(l,(bel[r]-1)*blo+1);i<=r;i++){ tmp=num[a[i]]+cnt[bel[r]-1][a[i]]-cnt[bel[l]][a[i]]; if(tmp>mx||(tmp==mx&&a[i]<ans)) ans=a[i],mx=tmp; } return ans; } int main(){ scanf("%d",&n); int q; scanf("%d",&q); blo=sqrt(n); for(int i=1;i<=n;i++){ bel[i]=(i-1)/blo+1; scanf("%d",&t[i].val); t[i].pos=i; } sort(t+1,t+n+1); int id=0; for(int i=1;i<=n;i++){ if(t[i].val!=t[i-1].val||i==1) id++; a[t[i].pos]=id; val[id]=t[i].val; } for(int i=1;i<=n;i++){//cnt[i][j] num[a[i]]++; if(i==bel[i]*blo||i==n) memcpy(cnt[bel[i]],num,sizeof(num)); } for(int i=1;i<=bel[n];i++){//g,f memset(num,0,sizeof(num)); int mx=0,ans=0; for(int j=(i-1)*blo+1;j<=n;j++){ num[a[j]]++; if(num[a[j]]>mx||(num[a[j]]==mx&&a[j]<ans)){ mx=num[a[j]]; ans=a[j]; } if(j==n||j%blo==0){ f[i][bel[j]]=ans; g[i][bel[j]]=mx; } } } int lastans=0; for(int i=1;i<=q;i++){ int l,r;scanf("%d%d",&l,&r); l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1; if(l>r) swap(l,r); lastans=val[query(l,r)]; printf("%d ",lastans); } }
以上是关于Luogu4168 [Violet]蒲公英的主要内容,如果未能解决你的问题,请参考以下文章