zoukankan      html  css  js  c++  java
  • bzoj 4299: Codechef FRBSUM 主席树

    题目大意: ... 自己看
    我们发现问题变成了给我们一些数,问我们最小的不能组合出来的数

    由于是多次询问,我们理所当然地想到使用数据结构

    首先对于这个问题我们有一个现成的解决方法:
      若([1,n])之内的数都可以被表示,那么如果假如一个数(x)满足((x leq n+1))
      则把x加入后我们可以表示([1,n+x])内的所有数
    所以我们从小到大选择区间内的数字,设当前我们可以表示出([1,n])之内的所有数
    那么我们判断所有$ le n+1(的数的和是否) ge n=1( 如果不满足,那说明我们求和的所有数都已经被加入到了集合中并且已经不存在这个一个x,那么)ans = n+1$
    如果满足,那说明存在一些 (x == n+1),(因为n一定在上次计算被计入)
    那么我们就让(n = sum),即当前可以表示的区间为([1,sum])

    所以我们就依据这个原理迭代即可。

    复杂度为(O(nlogn + m*(玄)))

    注:不要忘了开(long long)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(ll &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    inline ll cat_max(const ll &a,const ll &b){return a>b ? a:b;}
    inline ll cat_min(const ll &a,const ll &b){return a<b ? a:b;}
    const ll maxn = 200010;
    const ll maxnum = 1000000000;
    struct Node{
    	Node *ch[2];
    	ll sum;
    	void update(){
    		sum = ch[0]->sum + ch[1]->sum;
    	}
    }*null,*root[maxn];
    Node mem[maxn*20],*C;
    inline void init(){
    	C = mem;null = C++;
    	null->ch[0] = null->ch[1] = null;
    	null->sum = 0;root[0] = null;
    }
    Node* insert(Node *rt,ll l,ll r,ll pos){
    	Node *p = C++;*p = *rt;
    	if(l == r){
    		p->sum += pos;
    		return p;
    	}
    	ll mid = l+r >> 1;
    	if(pos <= mid) p->ch[0] = insert(rt->ch[0],l,mid,pos);
    	else p->ch[1] = insert(rt->ch[1],mid+1,r,pos);
    	p->update();return p;
    }
    ll query(Node *p1,Node *p2,ll l,ll r,ll x){
    	if(l > x) return 0;
    	if(r <= x) return p2->sum - p1->sum;
    	ll mid = l+r >> 1,ret = 0;
    	ret += query(p1->ch[0],p2->ch[0],l,mid,x);
    	if(x  > mid) ret += query(p1->ch[1],p2->ch[1],mid+1,r,x);
    	return ret;
    }
    int main(){
    	init();
    	ll n;read(n);
    	for(ll i=1,x;i<=n;++i){
    		read(x);
    		root[i] = insert(root[i-1],1,maxnum,x);
    	}
    	ll m;read(m);
    	ll s,t;
    	while(m--){
    		read(s);read(t);
    		ll nw = 1,la = -1;
    		while(1){
    		//	la = nw;
    			ll x = query(root[s-1],root[t],1,maxnum,nw);
    		//	printf("query :: %d get : %d
    ",nw,x);
    			if(x >= nw) nw = x+1;
    			else break;
    		//	if(nw == la) break;
    		}
    		printf("%lld
    ",nw);
    	}
    	getchar();getchar();
    	return 0;
    }
      
    
  • 相关阅读:
    zbb20180929 dubbo+zookeeper
    zbb20180929 Linux高可用之Keepalived
    zbb20180929 zk Zookeeper的功能以及工作原理
    zbb20180927 Union与Union All的区别
    zbb20180927 MySQL MyISAM InnoDB区别
    zbb20180921 spring事物的七种事物传播属性行为及五种隔离级别
    zbb20180921 java,md5,MD5加密+加盐
    zbb20180921 java,js,javascript 前端加密后端解密Base64通用加密处理
    zbb20180921 springboot 全局异常处理 404 500
    zbb20180919 db,mysql MySQL慢查询
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6344635.html
Copyright © 2011-2022 走看看