• BZOJ2120数颜色(带修改莫队)


    莫队算法是一种数据结构的根号复杂度替代品,主要应用在询问[l,r]到询问[l+1,r]和[l,r+1]这两个插入和删除操作复杂度都较低的情况下。具体思想是:如果把一个询问[l,r]看做平面上的点(l,r)的话,两个询问状态之间的转移代价可以看做这两个点的曼哈顿距离。这样我们可以通过预处理出曼哈顿最小生成树解决这类问题,但莫队算法可以直接在根号复杂度下解决。

    带修改莫队实际上是普通二维莫队的基础上增加了第三维(修改时间),这样就要求我们可以在较低复杂度下在某个区间内执行一个修改操作。以(l/B,r/B,t)为关键字,可以证明转移总复杂度为$O(n^{frac{5}{3}})$的。

    带修改莫队需要注意的地方:每个询问要记录这个询问之前的最后一个修改是哪个,每个修改要记录修改之前的值以方便撤销。修改函数要写两个,一个是执行某个修改操作,一个是没有修改地从某个[l,r]走到[l',r']。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=l; i<=r; i++)
     5 using namespace std;
     6 
     7 const int N=1000100;
     8 char s[10];
     9 struct P{ int l,r,id,t; }a[N];
    10 struct Q{ int x,y,lst; }b[N];
    11 int x,y,n,m,A,B,sum,l,r,t,cnt[N],v[N],ans[N],lst[N],bel[N];
    12 
    13 bool cmp(const P &x,const P &y){
    14     if (bel[x.l]!=bel[y.l]) return bel[x.l]<bel[y.l];
    15     if (bel[x.r]!=bel[y.r]) return bel[x.r]<bel[y.r];
    16     return x.t<y.t;
    17 }
    18 
    19 void mdf(int x,int y){
    20     if (x>=l && x<=r){
    21         cnt[v[x]]--; if (!cnt[v[x]]) sum--;
    22         v[x]=y;
    23         cnt[y]++; if (cnt[y]==1) sum++;
    24     }else v[x]=y;
    25 }
    26 
    27 void upd(int x,int y){
    28     int p=cnt[v[x]]; cnt[v[x]]+=y;
    29     if (!p && cnt[v[x]]) sum++;
    30     if (p && !cnt[v[x]]) sum--;
    31 }
    32 
    33 void work(){
    34     l=1,r=0,t=0;
    35     rep(i,1,A){
    36         while (t>a[i].t) mdf(b[t].x,b[t].lst),t--;
    37         while (t<a[i].t) t++,mdf(b[t].x,b[t].y);
    38         while (r<a[i].r) r++,upd(r,1);
    39         while (l>a[i].l) l--,upd(l,1);
    40         while (r>a[i].r) upd(r,-1),r--;
    41         while (l<a[i].l) upd(l,-1),l++;
    42         ans[a[i].id]=sum;
    43     }
    44 }
    45 
    46 int main(){
    47     freopen("bzoj2120.in","r",stdin);
    48     freopen("bzoj2120.out","w",stdout);
    49     scanf("%d%d",&n,&m); int B=sqrt(n);
    50     rep(i,1,n) scanf("%d",&v[i]),lst[i]=v[i],bel[i]=(i-1)/B+1;
    51     rep(i,1,m){
    52         scanf("%s%d%d",s,&x,&y);
    53         if (s[0]=='Q') a[++A]=(P){x,y,A,B}; else b[++B]=(Q){x,y,lst[x]},lst[x]=y;
    54     }
    55     sort(a+1,a+A+1,cmp); work();
    56     rep(i,1,A) printf("%d
    ",ans[i]);
    57     return 0;
    58 }
  • 相关阅读:
    springboot新手脱坑之无法下载依赖包
    07_mybatis延迟加载
    05_mybatis动态sql
    04_Mybatis输入出映射
    C#-----类FileStream的使用
    JavaWeb-----JSP详解
    JavaWeb-----ServletConfig对象和servletContext对象
    JavaWeb-----实现第一个Servlet程序
    JavaScript--浅谈!=、!==、==和===的区别
    EasyUI学习-----表格DataGrid格式化formatter用法
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8495928.html
Copyright © 2020-2023  润新知