zoukankan      html  css  js  c++  java
  • 【AT1219】歴史の研究(回滚莫队模板)

    点此看题面

    • 给定一个长度为(n)的序列。
    • 每次询问给定一个区间,定义一种颜色的价值为它的大小乘上它在这个区间内的出现次数,求所有颜色最大的价值。
    • (nle10^5)

    回滚莫队:加入+撤销

    这种区间询问的问题一般来说可以利用莫队解决。

    然而这道题求的是最大值,似乎普通莫队就无法很好地实现删除操作,因此就需要回滚莫队这种黑科技。

    考虑我们先暴力处理掉左端点和右端点在同一个块内的询问(显然这部分复杂度是(O(nsqrt n))的),然后对于剩余的询问把它扔到左端点对应块的(vector)中。

    然后,对于每一个左端点对应块,我们把其中的询问按右端点从小到大排序。

    对每个询问,我们只要加入上个右端点和当前右端点之间的数,接着加入左端点到块的右边界的所有数,并在询问结束后撤销左端点到块的右边界的修改。

    分析复杂度,对于一个块,右端点只会单调右移,总复杂度(O(nsqrt n));对于每个左端点,到所在块的右边界最多只有(O(sqrt n))个数,总复杂度也是(O(nsqrt n))

    因此,回滚莫队的复杂度依然是(O(nsqrt n))的!

    这道题的具体实现

    加入一个数直接修改计数数组并更新答案即可。

    而考虑撤销,只要在加入需要撤销的数(左端点到块的右边界的所有数)之前记录下原先的答案,在撤销时改回答案并直接修改计数数组撤销即可。

    应该算是一道比较板子的题目了吧。

    代码:(O(nsqrt n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define SN 320
    #define LL long long
    using namespace std;
    int n,Qt,a[N+5],dc,dv[N+5],sz,bl[N+5];LL ans[N+5];struct Q
    {
    	int p,l,r;I Q(CI i=0,CI a=0,CI b=0):p(i),l(a),r(b){}I bool operator < (Con Q& o) Con {return r<o.r;}
    };vector<Q> q[SN+5];vector<Q>::iterator it;
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char c,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(c=tc()));W(x=(x<<3)+(x<<1)+(c&15),isdigit(c=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    namespace RollBackMo//回滚莫队
    {
    	LL v;int c[N+5];I void A(CI x) {1LL*++c[x]*dv[x]>v&&(v=1LL*c[x]*dv[x]);}I void D(CI x) {--c[x];}//加入;撤销
    	I LL BF(CI l,CI r) {RI i;LL t=v;for(i=l;i<=r;++i) A(a[i]);for(i=r;i>=l;--i) D(a[i]);return swap(v,t),t;}//修改,并在询问后撤销
    }using namespace RollBackMo;
    int main()
    {
    	RI i;for(read(n),read(Qt),sz=sqrt(n),i=1;i<=n;++i) read(a[i]),dv[i]=a[i],bl[i]=(i-1)/sz+1;
    	for(sort(dv+1,dv+n+1),dc=unique(dv+1,dv+n+1)-dv-1,i=1;i<=n;++i) a[i]=lower_bound(dv+1,dv+dc+1,a[i])-dv;//离散化
    	RI x,y;for(i=1;i<=Qt;++i) read(x),read(y),bl[x]^bl[y]?(q[bl[x]].push_back(Q(i,x,y)),0):(v=0,ans[i]=BF(x,y));//同一个块直接暴力
    	RI R;for(i=1;i<=bl[n];++i) {sort(q[i].begin(),q[i].end()),R=i*sz,v=0;//初始化块的右端点在块的右边界,清空答案
    		for(it=q[i].begin();it!=q[i].end();ans[it->p]=BF(it->l,i*sz),++it) W(R^it->r) A(a[++R]);W(R>i*sz) D(a[R--]);}//单调移动右端点,暴力做左端点
    	for(i=1;i<=Qt;++i) writeln(ans[i]);return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    【SaltStack官方版】—— states教程, part 4
    【SaltStack官方版】—— states教程, part 3
    【SaltStack官方版】—— states教程, part 2
    斐波那契递归和非递归算法
    实现两个大数相乘
    快速排序算法
    HadoopMR-Spark-HBase-Hive
    windows10 conda python多版本切换
    websocket通信 实现java模拟一个client与webclient通信
    maven jsp out.print()request.getParameter() 爆红
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/AT1219.html
Copyright © 2011-2022 走看看