1 条题解
-
0
自动搬运
来自洛谷,原作者为

Twig_K
Life will be easier when the sunlight in搬运于
2025-08-24 23:12:16,当前版本为作者最后更新于2025-04-07 12:44:40,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
有 个整数,值域 。请你将这 个数划分为两个非空集合 ,并选择 。
要求 为 的众数之一, 为 的众数之一。最大化 的值。
组询问,每次询问前修改 。 。
题解
对于选出的 ,考虑如何贪心地划分集合:所有数 放入 ,所有数 放入 ,其他数摊到两个集合。
所以, 能被同时取出,当且仅当:
即:
既然要最大化下标差,那么我们可以对每种不同的 记录 的最大、最小下标 。
双指针,枚举 ,找到最大的 使 ,用 之差更新答案。
双指针移动 次,这样复杂度是 的,多组询问总复杂度 。
怎么优化呢?因为始终有 ,所以本质不同的 最多有 种(考虑 那么 是 的)。
所以只需要考虑那些不同的非零 即可,用
set维护存在的 值,再对每种 开一个set辅助求解最大、最小下标。时间复杂度 。
代码
int n,Q; set<int> st[maxn],S; int a[maxn],c[maxn],mxi[maxn],mni[maxn]; void addc(int i,int cl){ //i 的得票变成 cl 了 if(!cl) return; st[cl].insert(i); mxi[cl]=max(mxi[cl],i); mni[cl]=min(mni[cl],i); if(st[cl].size()==1) S.insert(cl); } void delc(int i,int cl){ //i 的得票不再是 cl 了 if(!cl) return; st[cl].erase(i); if(st[cl].empty()) S.erase(cl),mxi[cl]=0,mni[cl]=n+1; else if(!st[cl].empty()) mxi[cl]=*--st[cl].end(),mni[cl]=*st[cl].begin(); } signed main() { rd(n),rd(Q); For(i,1,n) rd(a[i]),c[a[i]]++,mxi[i]=0,mni[i]=n+1; For(i,1,n) addc(i,c[i]); while(Q--) { int i,x;rd(i),rd(x); delc(a[i],c[a[i]]--),addc(a[i],c[a[i]]); a[i]=x; delc(a[i],c[a[i]]++),addc(a[i],c[a[i]]); int mx=*--S.end(),mxp=0,mnp=n+1,res=0; if(*S.begin()+*S.begin()>=mx) res=max(res,mxi[*S.begin()]-mni[*S.begin()]); for(auto itl=S.begin(),itr=--S.end();itl!=S.end();itl++){//双指针 while(itr!=S.begin() && (*itr)+(*itl)>=mx) mxp=max(mxp,mxi[*itr]),mnp=min(mnp,mni[*itr]),itr--; res=max(res,max(mxp-mni[*itl],mxi[*itl]-mnp)); } write(res),End; } return 0; }
- 1
信息
- ID
- 11917
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者