主席树——求区间第k个不同的数字(向右密集hdu5919)
和向左密集比起来向右密集只需要进行小小的额修改,就是更新的时候从右往左更新。。
自己写的被卡死时间。不知道怎么回事,和网上博客的没啥区别。。
/*
给定一个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)的更多相关文章
- hdu4417 主席树求区间小于等于K
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 Problem Description Mario is world-famous plum ...
- 主席树--动态区间第k小
主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...
- poj 2104 主席树(区间第k大)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 44940 Accepted: 14946 Ca ...
- A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)
题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...
- HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)
HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...
- [csu/coj 1080]划分树求区间前k大数和
题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数 ...
- HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- 主席树——求区间[l,r]不同数字个数的模板(向左密集 D-query)
主席树的另一种用途,,(还有一种是求区间第k大,区间<=k的个数) 事实上:每个版本的主席树维护了每个值最后出现的位置 这种主席树不是以权值线段树为基础,而是以普通的线段树为下标的 /* 无修改 ...
- hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)
题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...
随机推荐
- Making every developer more productive with Visual Studio 2019
Today, in the Microsoft Connect(); 2018 keynote, Scott Guthrie announced the availability of Visual ...
- 【dp】摘花生
[题目描述] Hello Kitty想摘点花生送给她喜欢的米老鼠.她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来.地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经 ...
- django restframework Serializer field
SerializerMethodField 这是一个只读字段.它通过调用它所连接的序列化类的方法来获得它的值.它可用于将任何类型的数据添加到对象的序列化表示中. 签名: SerializerMetho ...
- python学习day19 面向对象(一)封装/多态/继承
面向对象 封装思想:将同一类的函数函数封装到同一个py文件中,方便调用 面向对象也有封装的作用,将同一类的函数封装到一个类中 多态(鸭子模型):多种类型/多种形态 #,什么事鸭子模型 对于一个函数,p ...
- SAM求多个串的最长公共子串
又学到一个\(SAM\)的新套路QvQ 思路 考虑用其中的一个串建个\(SAM\),然后用其他的串在上面匹配,匹配时更新答案 首先有一个全局变量\(len\),表示当前已匹配的长度.假设目前在点\(u ...
- Project 的ProjectTypeGuids和Solution的Project节点说明
https://www.cnblogs.com/jackking/p/6220085.html ProjectTypeGuids和Project 节点说明 <ProjectGuid>{BE ...
- PMP(项目管理)备考资料汇总-来自多名项目经理的总结
上重点,所有的相关总结文档(备考计划<务必仔细看一遍>.总结.提升方法等).含易混点区分的思维导图都在QQ群里:931269244 所有整理资料的汇总说明有时候别人会问我,你这是图什么呢, ...
- 20175221《Java程序设计》第9周学习总结
20175221 <Java程序设计>第9周学习总结 教材学习内容总结 第十一章主要内容有: MySQL数据库管理系统 下载mysql-8.0.16-winx64 启动MySQL数据库 ...
- Vue(小案例_vue+axios仿手机app)_购物车(计算商品总金额)
一.前言 1.计算总金额 2.点击删除按钮,删除对应的商品信息 3.当还没结算的时候,当用户跳到其他页面 ...
- MySQL实战45讲学习笔记:索引(第五讲)
一.需要回表的案例 在下面表T中,执行下面语句,需要执行几次树的搜索操作?会扫描多少行? select * from T where k between 3 and 5 1.初始化语句 mysql&g ...