首页 技术 正文
技术 2022年11月6日
0 收藏 945 点赞 254 浏览 1955 个字

【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;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,031
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,520
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,368
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,148
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,781
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,861