• [loj6746]区间众数


    枚举区间中点$x$,考虑$L$使得$x$为区间$[x-L,x+L]$的众数:

    记可重集$\{|i-x|\mid a_{i}=x\}$中的元素依次为$b_{1}\le b_{2}\le ...\le b_{k}$

    枚举出现次数$i\in [1,k]$,即要求$L\in [b_{i},b_{i+1})$,且合法的$L$是该区间的一个前缀

    当$k\ge \sqrt{n}$时,这类$x$仅有$o(\sqrt{n})$个,直接从小到大枚举$L$并维护众数即可

    当$k<\sqrt{n}$时,预处理出$pos_{r,i}$表示以$r$为右端点且众数出现次数$>i$的左端点

    此时,条件即$pos_{x+L,i}<x-L$,移项后$L+pos_{x+L,i}$具有单调性,二分即可

    具体实现中,$pos$可以用双指针求出,且需交换$i$和$x$的枚举顺序(空间限制)

    上述过程复杂度为$o(n\sqrt{n})$(注意二分仅有$n$次),并转换为以下问题:

    给定$n$组$(x,l_{L},r_{L})$,$m$次询问$\sum_{(x,l_{L},r_{L})}[l_{L},r_{L}]\cap [0,\min(x-l,r-x)]$

    记$mid=\lfloor\frac{l+r}{2}\rfloor$,对$x\in [l,mid]/(mid,r]$分类讨论,以下以前者为例——

    对$[l_{L},r_{L}]$差分并用$x$减去两项,最终结果即$\max(x-l_{L}+1,l)-\max(x-r_{L},l)$

    在此基础上,对$x$差分并做扫描线,用树状数组维护上述两值即可

    总复杂度为$o(n\sqrt{n}+m\log n)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 500005
      4 #define ll long long
      5 #define pii pair<int,int>
      6 #define fi first
      7 #define se second
      8 int n,m,K,l,r,num[21],a[N],cnt[N],pos[N];ll ans[N<<1];
      9 vector<int>v[N];vector<pii>vu[N],vq1[N],vq2[N];
     10 struct TA{
     11     ll f[N];
     12     int lowbit(int k){
     13         return (k&(-k));
     14     }
     15     void update(int k,int x){
     16         while (k<=n+1)f[k]+=x,k+=lowbit(k);
     17     }
     18     ll query(int k){
     19         ll ans=0;
     20         while (k)ans+=f[k],k^=lowbit(k);
     21         return ans;
     22     }
     23     ll query(int l,int r){
     24         return query(r)-query(l-1);
     25     }
     26 }F1,F2,F3,F4;
     27 int read(){
     28     int x=0;char c=getchar();
     29     while ((c<'0')||(c>'9'))c=getchar();
     30     while ((c>='0')&&(c<='9'))x=x*10+c-'0',c=getchar();
     31     return x;
     32 }
     33 void write(ll x,char c='\0'){
     34     while (x)num[++num[0]]=x%10,x/=10;
     35     if (!num[0])putchar('0');
     36     while (num[0])putchar(num[num[0]--]+'0');
     37     putchar(c);
     38 }
     39 int main(){
     40     n=read(),m=read(),K=(int)sqrt(n);
     41     for(int i=1;i<=n;i++){
     42         a[i]=read();
     43         v[a[i]].push_back(abs(i-a[i]));
     44     }
     45     for(int i=1;i<=n;i++)
     46         if (v[i].size()<K)sort(v[i].begin(),v[i].end());
     47         else{
     48             int mx=0,lst=-1;
     49             memset(cnt,0,sizeof(cnt));
     50             for(int j=0;j<=min(i-1,n-i);j++){
     51                 mx=max(mx,++cnt[a[i-j]]);
     52                 if (j)mx=max(mx,++cnt[a[i+j]]);
     53                 if (cnt[i]==mx){
     54                     if (lst<0)lst=j;
     55                 }
     56                 else{
     57                     if (lst>=0)vu[i].push_back(make_pair(lst,j-1)),lst=-1;
     58                 }
     59             }
     60             if (lst>=0)vu[i].push_back(make_pair(lst,min(i-1,n-i)));
     61         }
     62     for(int i=1;i<K;i++){
     63         int now=1,s=0;
     64         memset(cnt,0,sizeof(cnt));
     65         for(int j=1;j<=n;j++){
     66             s+=(cnt[a[j]]++==i);
     67             while (s>(cnt[a[now]]==i+1))s-=(--cnt[a[now++]]==i);
     68             pos[j]=(s ? now : -0x3f3f3f3f);
     69         }
     70         for(int j=1;j<=n;j++)
     71             if ((v[j].size()<K)&&(v[j].size()>=i)){
     72                 int l=v[j][i-1],r=min(j-1,n-j);
     73                 if (i<v[j].size())r=min(r,v[j][i]-1);
     74                 if ((l>r)||(pos[j+l]>=j-l))continue;
     75                 while (l<r){
     76                     int mid=(l+r+1>>1);
     77                     if (pos[j+mid]<j-mid)l=mid;
     78                     else r=mid-1;
     79                 }
     80                 vu[j].push_back(make_pair(v[j][i-1],l));
     81             }
     82     }
     83     for(int i=1;i<=m;i++){
     84         l=read(),r=read();
     85         int mid=(l+r>>1);
     86         vq1[l-1].push_back(make_pair(l,-i));
     87         vq1[mid].push_back(make_pair(l,i));
     88         vq2[mid].push_back(make_pair(r,-i));
     89         vq2[r].push_back(make_pair(r,i));
     90     }
     91     for(int i=1;i<=n;i++){
     92         for(pii j:vu[i]){
     93             F1.update(i-j.fi+1,1),F2.update(i-j.fi+1,i-j.fi+1);
     94             F1.update(i-j.se,-1),F2.update(i-j.se,j.se-i);
     95             F3.update(i+j.se,1),F4.update(i+j.se,i+j.se);
     96             if (i+j.fi>1)F3.update(i+j.fi-1,-1),F4.update(i+j.fi-1,1-i-j.fi);
     97         }
     98         for(pii j:vq1[i]){
     99             int l=j.fi,id=abs(j.se);
    100             ans[id]+=(j.se/id)*(l*F1.query(1,l)+F2.query(l+1,n+1));
    101         }
    102         for(pii j:vq2[i]){
    103             int r=j.fi,id=abs(j.se);
    104             ans[id]+=(j.se/id)*(r*F3.query(r+1,n+1)+F4.query(1,r));
    105         }
    106     }
    107     for(int i=1;i<=m;i++)write(ans[i],'\n');
    108     return 0;
    109 }
    View Code
  • 相关阅读:
    在微信小程序中使用富文本转化插件wxParse
    在微信小程序的JS脚本中使用Promise来优化函数处理
    结合bootstrap fileinput插件和Bootstrap-table表格插件,实现文件上传、预览、提交的导入Excel数据操作流程
    基于Metronic的Bootstrap开发框架经验总结(16)-- 使用插件bootstrap-table实现表格记录的查询、分页、排序等处理
    python 垃圾回收——分代回收 和java有些区别 注意循环引用无法被回收
    python del语句作用在变量上,而不是数据对象(常量)上
    for循环中的lambda与闭包——Python的闭包是 迟绑定 , 这意味着闭包中用到的变量的值,是在内部函数被调用时查询
    Python-try except else finally有return时执行顺序探究——finally语句无论如何也是会执行的
    你所不知道的Python | 字符串连接的秘密——连接大量字符串时 join和f-string都是性能最好的选择
    十大经典排序算法
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16425549.html
Copyright © 2020-2023  润新知