zoukankan      html  css  js  c++  java
  • CF484E Sign on Fence(主席树+二分答案)

    CF484E Sign on Fence

    前言

    主席树入门

    解题思路

    这个很好做。首先题目要我们求的是最小值的最大值,显然一眼就是二分答案,我们现在的问题就变成了怎样检验一个答案是否符合要求。

    比如说我们二分出来一个 (mid),那么我们需要检验在 ([l,r]) 之中是否存在长度为 (k) 的连续不比 (mid) 小的串。

    由于我们只关心数字与 (mid) 的大小关系,我们可以认为大于等于 (mid)(1),小于 (mid)(0)

    所以我们求的就是对于 (mid),最长连续为 (1) 的串长度是否大于等于 (k)

    容易想到对每个 (mid) 开线段树,但是时空爆炸,我们需另想妙招。

    可以用主席树来优化。

    此时我们把从大到小的所有 (mid) 对应的线段树全部求出来,最多修改 (n) 次,可以接受。

    至于怎么维护最长连续 (1),可以看其他博文,有详细解释,或者看我的代码也可以。

    注意要离散化,把值域修改为 ([1,n]),否则可能的 (mid) 值太多了。

    代码

    //Don't act like a loser.
    //This code is written by huayucaiji
    //You can only use the code for studying or finding mistakes
    //Or,you'll be punished by Sakyamuni!!!
    #include<bits/stdc++.h>
    #define int long long//别骂了
    using namespace std;
    
    int read() {
    	char ch=getchar();
    	int f=1,x=0;
    	while(ch<'0'||ch>'9') {
    		if(ch=='-')
    			f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') {
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return f*x;
    }
    
    const int MAXN=1e5+10;
    
    int n,m,q,cnt,tot;
    int num[MAXN],a[MAXN],root[MAXN],rt[MAXN];
    vector<int> vec[MAXN];
    struct seg_tree {
    	int llen,rlen,alen,ls,rs,len;
    }s[MAXN<<5];
    
    int new_node() {
    	return ++cnt;
    }
    void pushup(seg_tree &ans,seg_tree a,seg_tree b) {
    	ans.len=a.len+b.len;
    	
    	ans.alen=max(max(a.alen,b.alen),a.rlen+b.llen);
    	if(a.llen==a.len) {
    		ans.llen=a.llen+b.llen;
    	}
    	else {
    		ans.llen=a.llen;
    	}
    	if(b.rlen==b.len) {
    		ans.rlen=b.rlen+a.rlen;
    	}
    	else {
    		ans.rlen=b.rlen;
    	}
    }
    int build(int l,int r,int p) {
    	if(!p) {
    		p=new_node();
    	}
    	if(l==r) {
    		s[p].len=r-l+1;
    		s[p].llen=s[p].rlen=s[p].alen=0;
    		return p;
    	}
    	int mid=(l+r)>>1;
    	s[p].ls=build(l,mid,s[p].ls);
    	s[p].rs=build(mid+1,r,s[p].rs);
    	pushup(s[p],s[s[p].ls],s[s[p].rs]);
    	return p;
    }
    int modify(int l,int r,int p0,int p,int x) {
    	if(!p) {
    		p=new_node();
    	}
    	if(l==r) {
    		s[p].len=r-l+1;
    		s[p].llen=s[p].rlen=s[p].alen=1;
    		return p;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid) {
    		s[p].rs=s[p0].rs;
    		s[p].ls=modify(l,mid,s[p0].ls,s[p].ls,x);
    	}
    	else {
    		s[p].ls=s[p0].ls;
    		s[p].rs=modify(mid+1,r,s[p0].rs,s[p].rs,x);
    	}
    	pushup(s[p],s[s[p].ls],s[s[p].rs]);
    	return p;
    }
    seg_tree query(int l,int r,int p,int x,int y) {
    	if(y<l||r<x) {
    		return s[0];
    	}
    	if(x<=l&&r<=y) {
    		return s[p];
    	}
    	int mid=(l+r)>>1;
    	seg_tree ans=s[0];
    	pushup(ans,query(l,mid,s[p].ls,x,y),query(mid+1,r,s[p].rs,x,y));
    	return ans;
    }
    
    bool check(int l,int r,int k,int x) {
    	if(query(1,n,rt[x],l,r).alen>=k) {
    		return 1;
    	}
    	return 0;
    }
    signed main() {
    	cin>>n;
    	for(int i=1;i<=n;i++) {
    		a[i]=read();
    		num[i]=a[i];
    	}
    	sort(num+1,num+n+1);
    	m=unique(num+1,num+n+1)-num-1;
    	for(int i=1;i<=n;i++) {
    		a[i]=lower_bound(num+1,num+m+1,a[i])-num;
    		//cout<<a[i]<<endl;
    		vec[a[i]].push_back(i);
    	}
    	
    	root[0]=build(1,n,root[0]);
    	for(int i=m;i;i--) {
    		int sz=vec[i].size();
    		for(int j=0;j<sz;j++) {
    			tot++;
    			root[tot]=modify(1,n,root[tot-1],root[tot],vec[i][j]);
    		}
    		rt[i]=root[tot];
    	}
    	
    	cin>>q;
    	for(int i=1;i<=q;i++) {
    		int l,r,k;
    		l=read();r=read();k=read();
    		
    		int lft=1,rgt=m;
    		while(lft+1<rgt) {
    			int mid=(lft+rgt)>>1;
    			if(check(l,r,k,mid)) {
    				lft=mid;
    			}
    			else {
    				rgt=mid;
    			}
    		}
    		if(check(l,r,k,rgt)) {
    			printf("%lld
    ",num[rgt]);
    		}
    		else {
    			printf("%lld
    ",num[lft]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    数组静态初始化和动态初始化
    一维数组
    标识符啊
    常量定义
    11.08问题总结
    毕设(10.30)
    毕设(10.29)
    毕设(10.28)
    毕设(10.27)
    毕设(10.26)
  • 原文地址:https://www.cnblogs.com/huayucaiji/p/CF484E.html
Copyright © 2011-2022 走看看