• bzoj4241: 历史研究(回滚莫队)


    传送门

    这是一个叫做回滚莫队的神奇玩意儿

    是询问,而且不强制在线,就决定是你了莫队

    如果是每次插入一个数是不是很简单?

    然而悲剧的是我们莫队的时候不仅要插入数字还要删除数字

    那么把它变成只插入不就行了么?

    我们莫队将询问分块的时候,以左端点所在块为第一关键字,右端点(不是右端点所在块)为第二关键字

    对于每一个询问,如果左右端点在同一块中,直接暴力处理,复杂度(O(sqrt{n}))

    如果不在同一个块中呢?我们把所有左端点在同一块中的一起处理,那么右端点就是单调增的,这一部分只有插入,暴力计算的复杂度是(O(n))

    可是左端点的走位很飘啊?我们可以每一次都把左端点移到这一块的最右端,然后让它不断左移,那么这一部分也变成只有插入了

    于是总的复杂度为(O(nsqrt{n}))

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define ll long long
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R ll x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int N=1e5+5;
    int n,m;ll ans[N],res;
    int bl[N],cnt[N],b[N],a[N],tot,S;
    struct node{
    	int l,r,id;
    	node(){}
    	node(R int l,R int r,R int id):l(l),r(r),id(id){}
    	inline bool operator <(const node &b)const{return bl[l]==bl[b.l]?r<b.r:bl[l]<bl[b.l];}
    }q[N];
    inline void add(R int x){++cnt[a[x]],cmax(res,1ll*cnt[a[x]]*b[a[x]]);}
    ll solve(int l,int r){
    	static int cnt[N];ll res=0;
    	fp(i,l,r)cnt[a[i]]=0;
    	fp(i,l,r)++cnt[a[i]],cmax(res,1ll*cnt[a[i]]*b[a[i]]);
    	return res;
    }
    int calc(int i,int id){
    	int qr=min(n,id*S),r=qr;res=0;
    	memset(cnt,0,sizeof(cnt));
    	for(;bl[q[i].l]==id;++i){
    		if(bl[q[i].l]==bl[q[i].r]){ans[q[i].id]=solve(q[i].l,q[i].r);continue;}
    		while(r<q[i].r)add(++r);
    		ll ret=res;
    		fp(k,q[i].l,qr)add(k);
    		ans[q[i].id]=res;
    		fp(k,q[i].l,qr)--cnt[a[k]];
    		res=ret;
    	}return i;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),m=read(),S=sqrt(n);
    	fp(i,1,n)a[i]=b[i]=read(),bl[i]=(i-1)/S+1;
    	sort(b+1,b+1+n),tot=unique(b+1,b+1+n)-b-1;
    	fp(i,1,n)a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
    	fp(i,1,m)q[i].l=read(),q[i].r=read(),q[i].id=i;
    	sort(q+1,q+1+m);
    	for(R int i=1,id=1;id<=bl[n];++id)i=calc(i,id);
    	fp(i,1,m)print(ans[i]);
    	return Ot(),0;
    }
    
  • 相关阅读:
    iOS 数据持久化--CoreData
    iOS 数据持久化-- FMDB
    iOS数据持久化--数据库
    iOS数据持久化--归档
    iOS数据持久化--用户属性
    python爬坑记录
    Flutter 爬坑记录
    Web开发爬坑记录
    博客 新址: http://zhoushaoting.com/
    微信小程序开发技巧及填坑记录
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10375035.html
Copyright © 2020-2023  润新知