和向左密集比起来向右密集只需要进行小小的额修改,就是更新的时候从右往左更新。。

自己写的被卡死时间。不知道怎么回事,和网上博客的没啥区别。。

/*
给定一个n个数的序列a
每次询问区间[l,r],求出去重后区间中每个数的第一次出现的位置pi
pi构成一个新的升序,求这个新数组的中位数 要求强制在线,询问[l,r]根据上一个询问的答案进行加密,形成新的询问
t1=(l+ansi-1) % mod n + 1
t2=(r+ansi-1) % mod n + 1
l=min(t1,t2),r=max(t1,t2)
然后再进行询问即可 先求出a[i]在序列中上一次出现的位置pre[i]
从左往右进行一次扫描,用主席树来维护区间[1,i]的中不同数字的个数
询问[l,r]:
先求出区间出现的不同数字的个数k,具体操作见SPOJ D-QUERY
要求从左往右第k/2个数,很容易想到二分,在第r棵线段树上询问[mid,r]区间不同数字出现的个数,这样的复杂度是O(q*(logn)^2)
但这种做法是错的。。
出现这种情况是因为我们所有版本的线段树的点都是向后密集的,第i个棵线段树维护a[i]及之前的数最后出现的位置 所以只要每个版本的线段树中不同的数出现的位置能够向前密集,那么这个问题就转变成了求第k大的数
考虑如何将数据向前密集,即保存a[i]下一次出现的位置,扫到a[i]时将i+1,将下一次出现的位置-1即可
update:a[i]
所以从右往左更新主席树,nxt[i]-1,i+1
query:[l,r]
先在第l个版本的线段树上查询[1,r]区间的不同数字的个数l
在第l个版本的线段树上查询[1,r]范围内的第k/2大数的下标 可以发现这种主席树的查询其实退化成了线段树
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define INF 0x3f3f3f3f
struct Node{int lc,rc,sum;}t[maxn*];
int n,a[maxn],rt[maxn],size,nxt[maxn],pos[maxn];
int build(int l,int r){
int now=++size;
t[now].lc=t[now].rc=t[now].sum=;
if(l==r)return now;
int mid=l+r>>;
t[now].lc=build(l,mid);
t[now].rc=build(mid+,r);
return now;
}
int update(int last,int pos,int val,int l,int r){
int now=++size;
t[now]=t[last];t[now].sum+=val;
if(l==r)return now;
int mid=l+r>>;
if(pos<=mid)t[now].lc=update(t[last].lc,pos,val,l,mid);
else t[now].rc=update(t[last].rc,pos,val,mid+,r);
return now;
}
int query1(int rt,int L,int R,int l,int r){//查询区间[L,R]的和
if(L<=l && R>=r)return t[rt].sum;
int mid=l+r>>,res=;
if(L<=mid) res+=query1(t[rt].lc,L,R,l,mid);
if(R>mid)res+=query1(t[rt].rc,L,R,mid+,r);
return res;
}
int query2(int rt,int k,int l,int r){//查询线段树第k大的值
if(l==r)return l;
int mid=l+r>>;
if(k<=t[t[rt].lc].sum)return query2(t[rt].lc,k,l,mid);
else return query2(t[rt].rc,k-t[t[rt].lc].sum,mid+,r);
} int main(){
int T,q;cin>>T;
for(int tt=;tt<=T;tt++){
size=;memset(rt,,sizeof rt);
memset(nxt,0x3f,sizeof nxt);
memset(pos,0x3f,sizeof pos); scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=n;i>=;i--){
nxt[i]=pos[a[i]];
pos[a[i]]=i;
}
rt[n+]=build(,n);
for(int i=n;i>=;i--){
if(nxt[i]==INF)rt[i]=update(rt[i+],i,,,n);//直接在点i增加1
else {
int tmp=update(rt[i+],nxt[i],-,,n);
rt[i]=update(tmp,i,,,n);
}
} printf("Case #%d:",tt);
int ans=,l,r;
while(q--){
scanf("%d%d",&l,&r);
int t1=(l+ans)%n+,t2=(r+ans)%n+;
l=min(t1,t2),r=max(t1,t2);
int k=query1(rt[l],,r,,n);
ans=query2(rt[l],k/+k%,,n);//求第k个数的下标
printf(" %d",ans);
}
puts("");
}
}

下面的是ac的。。

#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=,t=;RG char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-')t=-,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
return x*t;
}
int tot,rt[MAX];
struct Node
{
int ls,rs;
int v;
}t[MAX<<];
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)>>;
if(p<=mid)Modify(t[x].ls,t[ff].ls,l,mid,p,w);
else Modify(t[x].rs,t[ff].rs,mid+,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)>>,ret=;
if(L<=mid)ret+=Query(t[r1].ls,l,mid,L,R);
if(R>mid)ret+=Query(t[r1].rs,mid+,r,L,R);
return ret;
}
int Kth(int r1,int l,int r,int K)
{
if(l==r)return l;
int mid=(l+r)>>,s=t[t[r1].ls].v;
if(s>=K)return Kth(t[r1].ls,l,mid,K);
else return Kth(t[r1].rs,mid+,r,K-s);
}
int ans,n,a[MAX],m;
int lst[MAX],pos[MAX];
int main()
{
int T=read();
for(int TTT=;TTT<=T;++TTT)
{
printf("Case #%d:",TTT);
memset(rt,,sizeof(rt));
memset(t,,sizeof(t));
memset(lst,,sizeof(lst));
memset(pos,,sizeof(pos));
tot=ans=;
n=read();m=read();
for(int i=;i<=n;++i)a[i]=read();
for(int i=n;i;--i)
if(!pos[a[i]])Modify(rt[i],rt[i+],,n,i,),pos[a[i]]=i;
else
{
Modify(rt[i],rt[i+],,n,i,);
Modify(rt[i],rt[i],,n,pos[a[i]],-);
pos[a[i]]=i;
}
while(m--)
{
int L=(read()+ans)%n+,R=(read()+ans)%n+;
if(L>R)swap(L,R);
int S=Query(rt[L],,n,L,R);
ans=Kth(rt[L],,n,(S+)/);
printf(" %d",ans);
}
puts("");
}
return ;
}

主席树——求区间第k个不同的数字(向右密集hdu5919)的更多相关文章

  1. hdu4417 主席树求区间小于等于K

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417   Problem Description Mario is world-famous plum ...

  2. 主席树--动态区间第k小

    主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...

  3. poj 2104 主席树(区间第k大)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 44940   Accepted: 14946 Ca ...

  4. A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)

    题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...

  5. HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

    HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...

  6. [csu/coj 1080]划分树求区间前k大数和

    题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数 ...

  7. HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  8. 主席树——求区间[l,r]不同数字个数的模板(向左密集 D-query)

    主席树的另一种用途,,(还有一种是求区间第k大,区间<=k的个数) 事实上:每个版本的主席树维护了每个值最后出现的位置 这种主席树不是以权值线段树为基础,而是以普通的线段树为下标的 /* 无修改 ...

  9. hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

    题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...

随机推荐

  1. nginx 详细配置

    Nginx全局变量 Nginx中有很多的全局变量,可以通过$变量名来使用.下面列举一些常用的全局变量: 变量 说明 boxClass 需要执行动画的元素的 变量 说明 $args 请求中的参数,如ww ...

  2. cinder-volume报错vmdk2 is reporting problems, not sending heartbeat. Service will appear "down".

    cinder-volume报错vmdk2 is reporting problems, not sending heartbeat. Service will appear "down&qu ...

  3. JDK源码分析(9) LinkedHashMap

    概述 LinkedHashMap是一个关联数组.哈希表,它是线程不安全的,允许key为null,value为null.他继承自HashMap,实现了Map<K,V>接口.其内部还维护了一个 ...

  4. Exp5 MSF基础应用

    一.实践内容 1.主动攻击实践 [1]MS08-067 MS08-067 漏洞是2008 年年底爆出的一个特大漏洞,存在于当时的所有微软系统,杀伤力超强.其原理是攻击者利用受害主机默认开放的SMB 服 ...

  5. H5_0007:使用base64做为背景图片

    page { overflow:hidden; position:fixed; /* background-image:url('http://p0d5ombx1.bkt.clouddn.com/lo ...

  6. 前端开发IDE VSCode + live preview

    live preview 为方便web开发者,编写网页静态代码,不用频繁切换到浏览器去查看的贴心功能. 可以在编辑器中,就实现编辑预览功能, 边编写代码,边查看预览效果. 与vscode相对应的其他两 ...

  7. windows的WSl安装mysql数据库以及操作数据库

    1.更新 sudo apt-get update sudo apt-get upgrade 2.安装mysql sudo apt-get install mysql-server 3.开启服务 sud ...

  8. JSP/Serlet 使用fileupload上传文件

    需要引用的jar commons-fileupload-1.3.1.jar commons-io-2.2.jar index.jsp <body> <center> <h ...

  9. JS数组(JSON)整合篇-方法整理

    遍历:arr_Param.forEach(function (item, i) {}); 反序排序:arr_Param.reverse(); 合并数组:arr_Param.push.apply(arr ...

  10. 关闭QQ右下角弹窗小程序

    关闭QQ右下角弹出的广告或新闻等. 程序没有界面,后台运行. #if defined(UNICODE) && !defined(_UNICODE) #define _UNICODE # ...