zoukankan      html  css  js  c++  java
  • P3332 [ZJOI2013]K大数查询

    题目

    P3332 [ZJOI2013]K大数查询

    一眼似乎不可做。。。结果眼瞎看错题了,切了切了

    做法

    化简题意:(n)个集合,(m)次操作(集合区间添数,集合区间查询(K)大值)

    外层值域线段树+内存区间线段树,自己去随便(yy)一下也能切掉吧

    还是讲一下具体做法:添的数(long long)以内,值域线段树空间会被卡,去重

    关于添数,找到(c)在值域内的位置,结果的线段树内层((a,b)+1),其实这个树套树维护的就是在((l,r))这个值域集合区间出现的数

    有点卡常:值域非递归做一下,(int)(long long)要准确区分位置,吸波氧可过

    My complete code

    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef int LL;
    const LL maxn=20000000;
    inline LL Read(){
    	LL x(0),f(1);char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    	return x*f;
    }
    struct Qy{
    	LL op,a,b;
    	long long c;
    }q[maxn];
    LL n,m,nod,cnt;
    LL son[maxn][2],root[maxn];
    long long tmp[maxn],sum[maxn],lazy[maxn];
    inline void Update(LL now){
    	sum[now]=sum[son[now][0]]+sum[son[now][1]];
    }
    inline void Pushdown(LL now,LL l,LL r){
    	LL val(lazy[now]);
    	if(val){
    		LL mid(l+r>>1);
    		lazy[now]=0;
    		if(!son[now][0]) son[now][0]=++nod;
    		if(!son[now][1]) son[now][1]=++nod;
    		LL lc(son[now][0]),rc(son[now][1]);
    		lazy[lc]+=val,lazy[rc]+=val,
    		sum[lc]+=(mid-l+1)*val,sum[rc]+=(r-mid)*val;
    	}
    }
    void Add(LL &now,LL l,LL r,LL lt,LL rt){
    	if(!now) now=++nod;
    	if(lt<=l&&rt>=r){
    		sum[now]+=(r-l+1),
    		++lazy[now];
    		return;
    	}
    	Pushdown(now,l,r);
    	LL mid(l+r>>1);
    	if(lt<=mid) Add(son[now][0],l,mid,lt,rt);
    	if(rt>mid)  Add(son[now][1],mid+1,r,lt,rt);
    	Update(now);
    }
    long long Query(LL now,LL l,LL r,LL lt,LL rt){
    	if(!now) return 0;
    	if(lt<=l&&rt>=r) return sum[now];
    	Pushdown(now,l,r);
    	LL mid(l+r>>1);long long ret(0);
    	if(lt<=mid) ret+=Query(son[now][0],l,mid,lt,rt);
    	if(rt>mid) ret+=Query(son[now][1],mid+1,r,lt,rt);
    	return ret;
    }
    void SAdd(LL x,LL l,LL r,LL c,LL a,LL b){
    	while(l!=r){
    		Add(root[x],1,n,a,b);
    		LL mid(l+r>>1);
    		if(c<=mid)
    			x=(x<<1),r=mid;
    		else
    			x=(x<<1|1),l=mid+1;
    	}
    	Add(root[x],1,n,a,b);
    }
    LL SQuery(LL x,LL l,LL r,LL a,LL b,long long K){
    	while(l!=r){
    		LL mid(l+r>>1);long long ret=Query(root[x<<1|1],1,n,a,b);
    		if(K<=ret)
    		    x=(x<<1|1),l=mid+1;
    		else
    		    x=(x<<1),r=mid,K-=ret;
    	}return tmp[l];
    }
    int main(){
    	n=Read(),m=Read();
    	for(LL i=1;i<=m;++i){
    		q[i]=(Qy){Read(),Read(),Read(),0};
    		scanf("%lld",&q[i].c);
    		if(q[i].op==1) tmp[++cnt]=q[i].c;
    	}
    	sort(tmp+1,tmp+1+cnt),cnt=unique(tmp+1,tmp+1+cnt)-tmp-1;
    	for(LL i=1;i<=m;++i){
    		if(q[i].op==1){
    			LL val(lower_bound(tmp+1,tmp+1+cnt,q[i].c)-tmp);
    			SAdd(1,1,cnt,val,q[i].a,q[i].b);
    		}else
    		    printf("%lld
    ",SQuery(1,1,cnt,q[i].a,q[i].b,q[i].c));
    	}return 0;
    }
    
  • 相关阅读:
    redis 内部数据结构 quicklist
    redis 七种内部数据结构
    魔漫相机
    情绪识别API
    AdressBook通讯录
    单例
    UI控件---UINavigationController导航栏控制器
    UI控件之UIScrollView
    UIScrollViewDelegate协议方法概述
    代理设计模式---传值
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10325695.html
Copyright © 2011-2022 走看看