zoukankan      html  css  js  c++  java
  • LUOGU P4587 [FJOI2016]神秘数(主席树)

    传送门

    解题思路

      如果区间内没有(1),那么答案就为(1),从这一点继续归纳。如果区间内有(x)(1),设区间内([2,x+1])的和为(sum),如果(sum=0),那么答案为(x+1),否则([1,x+sum])中的所有数字一定可以被表示,然后这个操作每次使答案至少扩大(1)倍,再用一个主席树维护,时间复杂度(O(nlognlogA))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    const int N=100005;
    const int M=N*33;
    const int inf=1000000000;
    typedef long long LL;
    
    template<class T> void rd(T &x){
    	x=0;char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    }	
    
    int n,m,a[N],rt[N],ls[M],rs[M],sum[M],cnt;
    LL Sum[M];
    
    void build(int &x,int l,int r,int k){
    	x=++cnt;
    	if(l==r) {sum[x]=1;Sum[x]=l;return ;}
    	int mid=(l+r)>>1;
    	if(k<=mid) build(ls[x],l,mid,k);
    	else build(rs[x],mid+1,r,k);
    	Sum[x]=Sum[ls[x]]+Sum[rs[x]];
    }
    
    void update(int pre,int &x,int l,int r,int k){
    	x=++cnt;ls[x]=ls[pre];rs[x]=rs[pre];
    	if(l==r) {sum[x]=sum[pre]+1;Sum[x]=Sum[pre]+l;return;}int mid=(l+r)>>1;
    	if(k<=mid) update(ls[pre],ls[x],l,mid,k);
    	else update(rs[pre],rs[x],mid+1,r,k);
    	Sum[x]=Sum[ls[x]]+Sum[rs[x]];
    }
    
    int query_tot(int u,int v,int l,int r,int k){
    	if(l==r) return sum[v]-sum[u];
    	int mid=(l+r)>>1;
    	if(k<=mid) return query_tot(ls[u],ls[v],l,mid,k);
    	else return query_tot(rs[u],rs[v],mid+1,r,k);	
    }
    
    LL query_sum(int u,int v,int l,int r,int L,int R){
    	if(L<=l && r<=R) return Sum[v]-Sum[u];
    	int mid=(l+r)>>1;LL ret=0;
    	if(L<=mid) ret+=query_sum(ls[u],ls[v],l,mid,L,R);
    	if(mid<R) ret+=query_sum(rs[u],rs[v],mid+1,r,L,R);
    	return ret;
    }
    
    int main(){
    	rd(n);rd(a[1]);build(rt[1],1,inf,a[1]);
    	for(int i=2;i<=n;i++)
    		rd(a[i]),update(rt[i-1],rt[i],1,inf,a[i]);
    	rd(m);int l,r,now,k,tot,lst;
    	while(m--){
    		rd(l),rd(r);k=0;lst=0;
    		while(1){
    			now=query_sum(rt[l-1],rt[r],1,inf,lst,k+1);
    			if(!now) break;lst=k+2;k=now+k;
    		}
    		printf("%d
    ",k+1);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    现代软件工程的构建之法
    How do I Check for Duplicate Items in a ListView?
    (转)aspxgridview记录的批量修改
    vs2010简体中文旗舰版智能感知,中文提示,英文提示变化的问题
    (转)怎样成为一名Android开发者
    It’s Not Too Late to Learn How to Code
    (转)手机屏幕VGA QVGA HVGA WVGA区别
    (转)CodeSmithSchemaExplorer类结构详细介绍
    (转)C#控件命名规范
    DataReader 绑定DataGridView的方式
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10254219.html
Copyright © 2011-2022 走看看