• [日常摸鱼]bzoj4358-莫队+线段树


    bzoj4358-莫队+线段树

    题意:给出一个长度为(n)的排列(P(P_1,P_2,...P_n)),以及(m)个询问。每次询问某个区间([l,r])中,最长的值域

    连续段长度(例如)。(n,mleq 5 imes 10^4)

    题解:

    (这题网上有挺多做法的,莫队+线段树/莫队+并查集/莫队+栈/KD-Tree,这里我原本是想找KD-Tree的题才找到这题的,但是没想到怎么做,用莫队做完去查了题解发现还需要一些前置知识,考虑到自己的学习进度好几天没往下推了,暂时还是不推支线了x,其他做法就先欠着吧x,KD树碰一碰就继续推主线去)

    就想着先把题做出来再说…于是其实就能很自然地想到用莫队来处理询问,很自然地去考虑一边处理区间一边维护一个值域序列(t[])(t[i])表示(i)这个数是否在区间内,接着要求的“最长值域连续长度”就成了序列上最长连续的1的长度,很经典的线段树的题:每个结点除了答案以外维护一个左端点开始的最长连续1和右端点开始的最长连续1,接着类似分治那样来维护(具体见代码的update)

    这样一来每次修改的代价都是(O(log n)),莫队处理询问自带一个根号,最终复杂度是(O(nsqrt n log n))的。

    const int N=5e4+5;
    const int M=240;
    struct query{
    	int l,r,idx;
    }Q[N];
    int n,m,T,bl[N],ans[N],a[N];
    int tr[N<<2],ls[N<<2],rs[N<<2];
    #define lson (node<<1)
    #define rson (node<<1|1)
    void update(int node,int l,int r){
    	int mid=(l+r)>>1;
    	tr[node]=max(tr[lson],max(tr[rson],ls[rson]+rs[lson]));
    	ls[node]=ls[lson];rs[node]=rs[rson];
    	if(ls[lson]==mid-l+1){
    		ls[node]+=ls[rson];
    		tr[node]=max(tr[node],ls[node]);
    	}
    	if(rs[rson]==r-mid){
    		rs[node]+=rs[lson];
    		tr[node]=max(tr[node],rs[node]);
    	}
    }
    void modify(int node,int l,int r,int x,int v){
    	if(l==r){
    		tr[node]+=v;
    		ls[node]=rs[node]=tr[node];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(mid>=x)modify(lson,l,mid,x,v);
    	else modify(rson,mid+1,r,x,v);
    	update(node,l,r);
    }
    #undef lson
    #undef rson
    bool cmp1(query p,query q){
    	if(bl[p.l]!=bl[q.l])return p.l<q.l;
    	return p.r<q.r;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	T=sqrt(n);
    	rep(i,1,n)bl[i]=(i-1)/T+1;
    	rep(i,1,n)scanf("%d",&a[i]);
    	rep(i,1,m)scanf("%d%d",&Q[i].l,&Q[i].r),Q[i].idx=i;
    	sort(Q+1,Q+m+1,cmp1);
    	int l,r;
    	l=Q[1].l;r=l-1;
    	rep(i,1,m)	{
    		int ql=Q[i].l,qr=Q[i].r;
    		while(l<ql){modify(1,1,n,a[l],-1);l++;}
    		while(l>ql){l--;modify(1,1,n,a[l],1);}
    		while(r<qr){r++;modify(1,1,n,a[r],1);}
    		while(r>qr){modify(1,1,n,a[r],-1);r--;}
    		ans[Q[i].idx]=tr[1];
    	}
    	rep(i,1,m)printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    pom.xml配置
    Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
    jar文件运行打断点
    prim算法
    Kruscal algorithm
    递归程序设计思想(看图思考2小时)
    广义表的实现(法二)
    广义表的实现
    有错误的地宫寻宝问题
    写一个数的所有加法算式
  • 原文地址:https://www.cnblogs.com/yoshinow2001/p/14458379.html
Copyright © 2020-2023  润新知