1 条题解

  • 0
    @ 2026-5-5 18:50:18

    赛时不会某个结论,被

    https://www.luogu.com.cn/user/565742

    下文认为 n,qn,q 同阶。

    令奶牛 xx 的得票数为 cxc_x,记 mx=maxi=1nci\mathrm{mx}=\max\limits_{i=1}^n c_i。显然两头奶牛 x,yx,y 能当选的充要条件为 cx+cymxc_x+c_y\ge\mathrm{mx}

    考虑一种 O(n2)O(n^2) 做法:对于每种 cc 的值 vv,找出最小和最大的 ii 满足 ci=vc_i=v,枚举其中一个出现次数 cxc_x,找出 cxc_x 对应的最小的 xminx_{\min},使用双指针找出 cymxcxc_y\ge\mathrm{mx}-c_x 中的 ymaxy_{\max},将所有情况取最大值即为答案。需要用到的值都可以用 set 维护。

    赛时卡在这一步了,但事实上上面的做法离正解就差一个十分关键的结论:若一个正整数序列 aa 满足 aiS\sum a_i\le S,那么 aa 中元素的种类数的量级是 O(S)O(\sqrt{S})。证明考虑如何卡满到这个上界,只需要构造 1,2,3,1,2,3,\ldots 即可。由于 ci=n\sum c_i=n,所以 cic_i 的值只有本质不同的 O(n)O(\sqrt{n}) 种。

    于是对于上面的暴力做法,如果只考虑至少对应着一个 xxcxc_x,时间复杂度就是 O(nn)O(n\sqrt{n}) 的。

    放代码:

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
      ios::sync_with_stdio(false);
      cin.tie(0); cout.tie(0);
      int n,q; cin>>n>>q;
      vector<int> a(n),c(n);
      for(auto &i:a)cin>>i,c[--i]++;
      vector<set<int> > s(n+1); set<int> v;
      // s 是每个 c 对应着那些 x
      // v 是至少对应着一个 x 的 c 的集合
      for(int i:a)s[c[i]].emplace(i),v.emplace(c[i]);
      while(q--){
        int p,x,r=0; cin>>p>>x,p--,x--;
        s[c[a[p]]].erase(a[p]);
        s[c[x]].erase(x);
        if(s[c[a[p]]].empty())v.erase(c[a[p]]);
        if(s[c[x]].empty())v.erase(c[x]);
        s[--c[a[p]]].emplace(a[p]);
        s[++c[x]].emplace(x);
        v.emplace(c[a[p]]),v.emplace(c[x]),a[p]=x;
        vector<int> e(v.begin(),v.end());
        for(int i=0,p=e.size()-1,mx=0;i<e.size();i++)
          if(e[i]){
            while(p>=0&&e[p]&&e[p]+e[i]>=e.back())
              mx=max(mx,*prev(s[e[p]].end())),p--;
            r=max(r,mx-*s[e[i]].begin());
          } // 双指针求解过程
        cout<<r<<'\n';
      }
      return 0;
    }
    
    • 1

    信息

    ID
    1566
    时间
    3000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    37
    已通过
    6
    上传者