• 【HDU5919】SequenceII(主席树)


    【HDU5919】SequenceII(主席树)

    题面

    Vjudge
    翻译(by ppl)

    给一个长度为N的数列A,有m个询问,每次问
    数列[l,r]区间中所有数的第一次出现的位置的中位
    数是多少
    

    题解

    先考虑一下怎么求区间内有多少个不同的数
    方法有两种

    第一种:
    记录一下每个数上一次出现的位置
    每次将这个位置+1
    最后求(l,r)区间内的数的个数
    也就是求区间内上一次出现的位置在(l)左侧的数的个数
    直接查询区间和即可

    第二种:
    将序列到过来插入
    每次记录这个数上一次出现的位置(倒过来的!!!)
    然后将上一次出现的位置-1
    这一次出现的位置+1
    每次询问(l,r)
    直接查询第(l)棵主席树中(l,r)的区间和即可

    这道题目既然要求所有的第一次出现的数的位置的中位数
    显然要维护位置信息,所以考虑第二种方法,
    第一种维护的是上一次出现位置的信息

    查询一下区间内有多少个数,然后求区间第(K)大的位置即可

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 222222
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int tot,rt[MAX];
    struct Node
    {
    	int ls,rs;
    	int v;
    }t[MAX<<5];
    void Modify(int &x,int ff,int l,int r,int p,int w)
    {
    	t[x=++tot]=t[ff];t[x].v+=w;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(p<=mid)Modify(t[x].ls,t[ff].ls,l,mid,p,w);
    	else Modify(t[x].rs,t[ff].rs,mid+1,r,p,w);
    }
    int Query(int r1,int l,int r,int L,int R)
    {
    	if(L<=l&&r<=R)return t[r1].v;
    	int mid=(l+r)>>1,ret=0;
    	if(L<=mid)ret+=Query(t[r1].ls,l,mid,L,R);
    	if(R>mid)ret+=Query(t[r1].rs,mid+1,r,L,R);
    	return ret;
    }
    int Kth(int r1,int l,int r,int K)
    {
    	if(l==r)return l;
    	int mid=(l+r)>>1,s=t[t[r1].ls].v;
    	if(s>=K)return Kth(t[r1].ls,l,mid,K);
    	else return Kth(t[r1].rs,mid+1,r,K-s);
    }
    int ans,n,a[MAX],m;
    int lst[MAX],pos[MAX];
    int main()
    {
    	int T=read();
    	for(int TTT=1;TTT<=T;++TTT)
    	{
    		printf("Case #%d:",TTT);
    		memset(rt,0,sizeof(rt));
    		memset(t,0,sizeof(t));
    		memset(lst,0,sizeof(lst));
    		memset(pos,0,sizeof(pos));
    		tot=ans=0;
    		n=read();m=read();
    		for(int i=1;i<=n;++i)a[i]=read();
    		for(int i=n;i;--i)
    			if(!pos[a[i]])Modify(rt[i],rt[i+1],1,n,i,1),pos[a[i]]=i;
    			else
    			{
    				Modify(rt[i],rt[i+1],1,n,i,1);
    				Modify(rt[i],rt[i],1,n,pos[a[i]],-1);
    				pos[a[i]]=i;
    			}
    		while(m--)
    		{
    			int L=(read()+ans)%n+1,R=(read()+ans)%n+1;
    			if(L>R)swap(L,R);
    			int S=Query(rt[L],1,n,L,R);
    			ans=Kth(rt[L],1,n,(S+1)/2);
    			printf(" %d",ans);
    		}
    		puts("");
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    学生3D作品---李自立---熊猫(Blender 2.8)
    学生3D作品---李自立---台式电脑加椅子(Blender 2.8)
    Tweak Kernel’s Task Scheduler to Boost Performance on Android [Part 2]
    Tweak Kernel’s Task Scheduler to Boost Performance on Android [Part 1]
    Binder transactions in the bowels of the Linux Kernel
    操作系统原理——实验——作业命名格式
    Linux 引入自动化测试平台 KernelCI
    进程可创建的最大连接数
    Docker—PaaS—微服务
    3D学院人才培养的金字塔模型-张同光-20190924---发言稿
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8694571.html
Copyright © 2020-2023  润新知