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

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

/*
给定一个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. 关于ES6

    一.变量声明const和let 变量提升:在ES6之前,我们都是用var关键字声明变量.无论声明在何处,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部).这就是函数变量提升例如: fu ...

  2. 【THUSC2017】【LOJ2977】巧克力 斯坦纳树

    题目大意 有一个网格(或者你可以认为这是一个图),每个点都有颜色 \(c_i\) 和点权 \(a_i\). 求最小的连通块,满足这个连通块内点的颜色数量 \(\geq k\).在满足点数最少的前提下, ...

  3. 洛谷 P5110 块速递推

    题目大意: 给定一个数列a满足递推式 \(An=233*an-1+666*an-2,a0=0,a1=1\) 求这个数列第n项模\(10^9+7\)的值,一共有T组询问 \(T<=10^7\) \ ...

  4. TJOI2018Party

    题目描述 小豆参加了\(NOI\)的游园会,会场上每完成一个项目就会获得一个奖章,奖章 只会是\(N\), \(O\), \(I\)的字样.在会场上他收集到了\(K\)个奖章组成的串. 兑奖规则是奖章 ...

  5. P1996 约瑟夫问题-题解(队列??明明是单循环链好吗)

    一如既往的题目传送:     https://www.luogu.org/problemnew/show/P1996 这里不讲数组模拟的方法(毕竟多做点题的模拟功力足以暴力出这道题),而是讲一种单循环 ...

  6. 第四周博客作业<西北师范大学|李晓婷>

    1.助教博客链接:https://home.cnblogs.com/u/lxt-/ 2.作业要求链接:www.cnblogs.com/nwnu-daizh/p/10487329.html 3.本周点评 ...

  7. sklearn中的损失函数

    python风控评分卡建模和风控常识(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005214003&am ...

  8. Hbase-site.xml

    生产环境基于 HA HDFS 的Hbase 基本优化后配置(无安全版本) hbase.rest.port 60050 hbase.cluster.distributed true hbase.root ...

  9. PHP安装文件的审计

    初始化安装 一般php程序都有一个初始安装的问题,如果使用了一些cms安装后且没有删除安装文件的话,就会导致二次安装等问题. 具体但不限于以下几种情况: 无验证功能,任意重装覆盖 $_GET['ste ...

  10. 【C++笔记】explicit 指定符

    用于抑制构造函数的自动隐式转换. struct A { A(int) { } // 转换构造函数 A(int, int) { } // 转换构造函数 (C++11) operator bool() c ...