加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

【差分主席树】zjoi2013 k大数

发布时间:2020-12-14 03:32:04 所属栏目:大数据 来源:网络整理
导读:这道题的解法挺多,值域线段树套区间线段树,区间线段树套值域线段树(目前想到的是zkw的标记永久化),cdq分治 相对好写一点的就是维护差分主席树,每个位置维护与前一个位置的数集差分,修改就可以看做是单点修改,然后再反推前缀和http://blog.csdn.net/h

这道题的解法挺多,值域线段树套区间线段树,区间线段树套值域线段树(目前想到的是zkw的标记永久化),cdq分治

相对好写一点的就是维护差分主席树,每个位置维护与前一个位置的数集差分,修改就可以看做是单点修改,然后再反推前缀和http://blog.csdn.net/huyuncong/article/details/6440979

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
const long long oo=1LL<<50;
using namespace std;
int l[2][5000000],st[2][5000000][2],r[2][5000000];
long long sum[2][5000000];
int ss[2],n,m,root[2][5000000];
int ori(int e)
{
    ++ss[e];
    l[e][ss[e]]=r[e][ss[e]]=sum[e][ss[e]]=0;
    return ss[e];
}
void change(int e,int x,long long L,long long R,long long c,int w) 
{
    if (L==R) {
        sum[e][x]+=w;
        return ;
    }
    long long mid=(L+R)>>1;
    if (c<=mid) {
        if (!l[e][x]) l[e][x]=ori(e);
        change(e,l[e][x],L,mid,c,w);
    }
    else {
        if (!r[e][x]) r[e][x]=ori(e);
        change(e,r[e][x],mid+1,R,w);
    }
    sum[e][x]=sum[e][l[e][x]]+sum[e][r[e][x]];
}
void origin()
{
    ss[0]=ss[1]=0;
    for (int i=1;i<=n;i++)
        root[0][i]=ori(0),root[1][i]=ori(1);
}
int lowbit(int x)
{
    return x & -x;
}
void modify(int x,int c,int w)
{
		int X=x;
    for (;x<=n;x+=lowbit(x))
        change(0,root[0][x],1,oo+oo,oo+c,1*w),change(1,root[1][x],X*w);
}
long long ask(int e,int t,int k)
{
    long long Sum=0;
    for (int i=1;i<=t;i++)
    	Sum+=sum[k][r[k][st[e][i][k]]];
    return Sum;
}
void Lstep(int e,int t)
{
	for (int i=1;i<=t;i++) 
		for (int k=0;k<=1;k++)
			st[e][i][k]=l[k][st[e][i][k]];
}
void Rstep(int e,int t)
{
	for (int i=1;i<=t;i++) 
		for (int k=0;k<=1;k++)
			st[e][i][k]=r[k][st[e][i][k]];
}
long long query(int l,int r,int k)
{
    int t[2]={0,0};
    for (int x=l-1;x;x-=lowbit(x))
        st[0][++t[0]][0]=root[0][x],st[0][t[0]][1]=root[1][x];
    for (int x=r;x;x-=lowbit(x))
        st[1][++t[1]][0]=root[0][x],st[1][t[1]][1]=root[1][x];
	long long L=1,R=oo+oo;
    for (;L!=R;) {
    		long long mid=(L+R)>>1;
    		long long sum1=(l-1+1)*ask(0,t[0],0)-ask(0,1);
    		long long sum2=(r+1)*ask(1,t[1],0)-ask(1,1);
        long long sum=sum2-sum1;
        //cout<<mid-oo<<' '<<sum<<endl;
        //cout<<"zz "<<ask(0,t)<<' '<<ask(1,t)<<endl;
        if (sum>=k) {
            L=mid+1;
            Rstep(0,t[0]);
            Rstep(1,t[1]);
        }
        else {
            R=mid;
            k-=sum;
            Lstep(0,t[0]);
            Lstep(1,t[1]);
        }
    }
    return L;
}
int main()
{
	freopen("input.txt","r",stdin);
    scanf("%d%d",&n,&m);
    origin();
    for (int i=1;i<=m;i++) {
        int c;
        scanf("%d",&c);
        if (1==c) {
            int l,r,c;
            scanf("%d%d%d",&l,&r,&c);
            modify(l,1);
            modify(r+1,-1);
        }
        else {
            int l,k;
            scanf("%d%d%d",&k);
            long long ans=query(l,k);
            printf("%dn",(int)(ans-oo));
        }
    }
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读