• [BZOJ3110][ZJOI2013]K大数查询


    BZOJ
    Luogu
    Description
    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
    如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
    Input
    第一行N,M
    接下来M行,每行形如1 a b c或2 a b c
    Output
    输出每个询问的结果
    Sample Input
    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3
    Sample Output
    1
    2
    1
    HINT
    N,M<=50000,N,M<=50000
    a<=b<=N
    1操作中abs(c)<=N
    2操作中c<=Maxlongint

    sol

    树套树题解
    线段树套线段树,注意内层是动态开节点。
    先确定内外层关系:外层表示数值,内层表示区间。(你可以试一试反过来)
    那么修改操作就是外层的单点修改,而实际上应该是单点到根的路径上的节点的修改,即我们要修改log棵线段树。在每个线段树里面是区间加1。可以直接写标记永久化(练一波手)
    查询时在外层二分,就是常规的求第k大,只是每次算右儿子size的时候都要在右儿子那棵线段树上查一下区间和。
    外层线段树直接用循环代替
    代码好写得很

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 50005;
    #define ll long long
    struct segment_tree{
    	int ls,rs,tim;ll num;
    }t[N*300];
    int n,m,rt[N*16],tot;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    void Modify(int &x,int l,int r,int ql,int qr)
    {
    	if (!x) x=++tot;
    	if (l==ql&&r==qr) {t[x].tim++;return;}
    	t[x].num+=qr-ql+1;
    	int mid=l+r>>1;
    	if (qr<=mid) Modify(t[x].ls,l,mid,ql,qr);
    	else if (ql>mid) Modify(t[x].rs,mid+1,r,ql,qr);
    	else Modify(t[x].ls,l,mid,ql,mid),Modify(t[x].rs,mid+1,r,mid+1,qr);
    }
    ll Query(int x,int l,int r,int ql,int qr)
    {
    	ll res=1ll*t[x].tim*(qr-ql+1);
    	if (l==ql&&r==qr) return res+t[x].num;
    	int mid=l+r>>1;
    	if (qr<=mid) return res+Query(t[x].ls,l,mid,ql,qr);
    	else if (ql>mid) return res+Query(t[x].rs,mid+1,r,ql,qr);
    	else return res+Query(t[x].ls,l,mid,ql,mid)+Query(t[x].rs,mid+1,r,mid+1,qr);
    }
    int main()
    {
    	n=gi();m=gi();
    	while (m--)
    	{
    		int opt=gi(),a=gi(),b=gi(),c=gi(),now=1,l=1,r=n;
    		if (opt==1)
    			while (233)
    			{
    				Modify(rt[now],1,n,a,b);
    				if (l==r) break;
    				int mid=l+r>>1;
    				if (c<=mid) now=now<<1,r=mid;
    				else now=now<<1|1,l=mid+1;
    			}
    		else
    			while (l<r)
    			{
    				ll sum=Query(rt[now<<1|1],1,n,a,b);
    				int mid=l+r>>1;
    				if ((ll)c<=sum)
    					now=now<<1|1,l=mid+1;
    				else c-=sum,now=now<<1,r=mid;
    			}
    		if (opt==2) printf("%d
    ",l);
    	}
    	return 0;
    }
    
  • 相关阅读:
    可以让你少奋斗十年的工作经验 .
    MFC多线程编的可能
    MFC中使用ADO方式连接数据库
    vc 获取当前时间
    mfc EDIT字体颜色
    使用css让div半透明
    -----日积月累-----
    TP框架 ---空控制器和空操作
    TP框架常用配置
    TP框架主要文件夹注释
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8258635.html
Copyright © 2020-2023  润新知