HDU - 5919 Sequence II(主席树+思维)
题目链接:点击查看
题目大意:给出一个长度为 n 的数列 a ,再给出 m 次询问,每次询问给出一个区间 [ l , r ] ,问区间 [ l , r ] 内首次出现的数字的位置的中位数
题目分析:题目可能比较绕,但是涉及到区间内第 k 大的问题不难想到主席树了,现在问题就是思考如何利用首次出现的数字这个条件
如果换种问法,问最后一次出现数字的位置,我们不难联想到主席树解决区间内有多少个本质不同的数字这道题目,这道题目实质上就是维护每个数字最后一次出现的位置,所以回到这个题目来,首次出现的位置,我们可以将整个数列倒过来维护,这样根 root[ i ] 代表的那个权值线段树的意义就是,区间 [ i , n ] 内每个数字首次出现的位置了,对于区间 [ l , r ] ,我们可以在 root[ l ] 这棵权值线段树上,查找区间 [ l , r ] 内有多少个不同的数,再求第 k 大就好了
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;struct Node
{int l,r;int sum;
}tree[N*50];int cnt,root[N],ans[N],a[N],pre[N];void init(int pos)
{memset(pre,0,sizeof(pre));root[pos]=0;tree[pos].l=tree[pos].r=tree[pos].sum=0;cnt=1;
}void change(int pos,int &k,int l,int r,int val)
{tree[cnt++]=tree[k];k=cnt-1;tree[k].sum+=val;if(l==r)return;int mid=l+r>>1;if(pos<=mid)change(pos,tree[k].l,l,mid,val);elsechange(pos,tree[k].r,mid+1,r,val);
}int query_sum(int rt,int l,int r,int L,int R)
{if(R<l||L>r)return 0;if(L>=l&&R<=r)return tree[rt].sum;int mid=L+R>>1;return query_sum(tree[rt].l,l,r,L,mid)+query_sum(tree[rt].r,l,r,mid+1,R);
}int query_kth(int rt,int l,int r,int k)
{if(l==r)return l;int mid=l+r>>1;if(tree[tree[rt].l].sum>=k)return query_kth(tree[rt].l,l,mid,k);elsereturn query_kth(tree[rt].r,mid+1,r,k-tree[tree[rt].l].sum);
}int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){int n,m;scanf("%d%d",&n,&m);init(n+1);for(int i=1;i<=n;i++)scanf("%d",a+i);for(int i=n;i>=1;i--){root[i]=root[i+1];if(pre[a[i]])change(pre[a[i]],root[i],1,n,-1);change(i,root[i],1,n,1);pre[a[i]]=i;}for(int i=1;i<=m;i++){int l,r;scanf("%d%d",&l,&r);l=(l+ans[i-1])%n+1;r=(r+ans[i-1])%n+1;if(l>r)swap(l,r);int k=(query_sum(root[l],l,r,1,n)+1)/2;ans[i]=query_kth(root[l],1,n,k);}printf("Case #%d:",++kase);for(int i=1;i<=m;i++)printf(" %d",ans[i]);puts("");}return 0;
}
HDU - 5919 Sequence II(主席树+思维)相关推荐
- HDU - 5919 Sequence II——主席树+区间种类++逆序建树
[题目描述] HDU - 5919 Sequence II [题目分析] 题目给定一个数组,每次查询一个区间,找出区间内不同数字的个数x,然后输出按出现顺序第x/2向上取整个数字的位置. 按照要求,我 ...
- HDU 5919 Sequence II 主席树
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5919 Sequence II Time Limit: 9000/4500 MS (Java/Othe ...
- HDU - 5919 Sequence II
题意: 给定长度为n的序列和q次询问.每次询问给出一个区间(L,R),求出区间内每个数第一次出现位置的中位数,强制在线. 题解: 用主席树从右向左的插入点.对于当前点i,如果a[i]出现过,则把原位置 ...
- Hdu-5919 Sequence II(主席树在线求区间不同数)
Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,⋯,an There a ...
- hdu 3397 Sequence operation(线段树,lazy,区间合并)
hdu 3397 Sequence operation 线段树lazy和区间合并结合的一个题,相当于几个题集中到一起嘛,分开想就好了 0,1,2操作都要lazy,2的异或操作找到每一只含1或只含0的区 ...
- CodeForces - 813E Army Creation(主席树+思维)
题目链接:点击查看 题目大意:给出一个长度为 nnn 的数列和一个整数 kkk,现在有 qqq 次询问,每次询问给出一个区间 [l,r][l,r][l,r],设 cnticnt_icnti 为数字 ...
- 牛客 - 牛牛的mex(主席树/思维)
题目链接:点击查看 题目大意:给出一个长度为 n 的排列,再给出 m 次询问,每次询问需要回答区间 [ l , r ] 的 mex 题目分析:算是一道比较经典的题目了吧,先说一般做法,一般做法是 nl ...
- 2021牛客暑期多校训练营7 K-xay loves sequence(主席树+二分)
K-xay loves sequence 首先不考虑模kkk的限制,容易想到对原数组做一个差分得到di=ai−ai−1d_i=a_i-a_{i-1}di=ai−ai−1,显然对于∀1≤i≤nai ...
- HDU - 4348To the moon——主席树+区间修改
HDU - 4348To the moon [题目描述] [题目分析] 题目中说明每次更新后时间都会加1,而且还会需要查询以前的区间,还会需要返回以前的时间,所以是很裸的主席树.区间查询的话我们同样需 ...
最新文章
- 实验 7:流类库与输入输出
- 一个整数转换成字符串(C/C++自己写的算法)
- Oracle BBED 工具介绍
- HTTP(超文本传输协议)
- JS生成UUID唯一标识方法
- php微信消息通知,php实现微信小程序消息通知
- 《CSS 揭秘》每章详细读书笔记
- 关于Google大陆手机号不能验证的问题
- 台式计算机连接无线,台式电脑怎么连WiFi无线网络
- 移动端名片识别SDK
- mac os壁纸软件_如何在Mac OS X上更改桌面墙纸
- 数电实验:数字时钟设计 (经验分享,仅供参考)
- 叠片过滤器和叠片式过滤器以及盘式过滤器的区别介绍
- Linux/Unix开发之make和makefile详解
- Git工具和CODING平台
- Eclipse java 字体的设置(最佳字体推荐)
- shell脚本之n之内的质数
- linux u盘 命令,制作U盘版linux系统安装盘(DD命令)
- dllcache的详细说明
- ChatGPT+ “剪映 or 百度AIGC” 快速生成短视频