题意:有A1 ~ An组成的数组,给你l r,L = min((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),R = max((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),你先需要的到L,R区间有k个不同的数字,然后问你L,R区间第(k + 1)/ 2个不同的数字下标是多少?

思路:显然是个在线询问。

我们之前已经会用主席树求区间内有多少不同数字了:从左到右把每个数字的位置存进每个操作的线段树,如果之前这个数已经出现,就在当前这棵线段树中删掉之前出现的位置,以保证每个数字出现的唯一性。显然每个区间保存的是某个数字最右边出现的位置。

但是这里显然我们不能去直接求第(k + 1)/ 2个不同的数字下标,因为我这里要求的是最早出现第(k + 1)/ 2个数的位置。那我直接从n往1建主席树,那我就变成了每个区间保存的是某个数字最左边出现的位置,显然我第i棵树并没有保存i前面的位置,那我就可以直接求i到后面任意位置的区间的第p个不相同数出现的位置。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + ;
const int M = maxn * ;
const ull seed = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
int a[maxn], root[maxn], tot;
int n, q;
struct node{
int lson, rson;
int sum;
}T[maxn * ];
int fa[maxn], ans[maxn];
void init(){
tot = ;
memset(fa, -, sizeof(fa));
memset(T, , sizeof(T));
}
void update(int l, int r, int &now, int pre, int pos, int v){
T[++tot] = T[pre], now = tot;
T[now].sum += v;
if(l == r) return;
int m = (l + r) >> ;
if(pos <= m)
update(l, m, T[now].lson, T[pre].lson, pos, v);
else
update(m + , r, T[now].rson, T[pre].rson, pos, v);
}
int query1(int l, int r, int L, int R, int now){
if(L <= l && R >= r){
return T[now].sum;
}
int m = (l + r) >> , sum = ;
if(L <= m)
sum += query1(l, m, L, R, T[now].lson);
if(R > m)
sum += query1(m + , r, L, R, T[now].rson);
return sum;
}
int query2(int l, int r, int now, int k){
if(l == r) return l;
int m = (l + r) >> ;
int sum = T[T[now].lson].sum;
if(sum >= k)
return query2(l, m, T[now].lson, k);
else
return query2(m + , r, T[now].rson, k - sum);
}
int main(){
int ca = , t;
scanf("%d" ,&t);
while(t--){
init();
scanf("%d%d", &n, &q);
root[n + ] = ;
for(int i = ; i <= n; i++)
scanf("%d", &a[i]);
for(int i = n; i >= ; i--){
if(fa[a[i]] == -){
update(, n, root[i], root[i + ], i, );
fa[a[i]] = i;
}
else{
update(, n, root[i], root[i + ], i, );
update(, n, root[i], root[i], fa[a[i]], -);
fa[a[i]] = i;
}
}
ans[] = ;
for(int i = ; i <= q; i++){
int l, r, L, R, k;
scanf("%d%d", &l, &r);
L = min((l + ans[i - ]) % n + , (r + ans[i - ]) % n + );
R = max((l + ans[i - ]) % n + , (r + ans[i - ]) % n + );
k = query1(, n, L, R, root[L]);
ans[i] = query2(, n, root[L], (k + ) / );
}
printf("Case #%d:", ca++);
for(int i = ; i <= q; i++)
printf(" %d", ans[i]);
printf("\n");
} return ;
}

HDU 5919 Sequence II(主席树)题解的更多相关文章

  1. HDU 5919 Sequence II 主席树

    Sequence II Problem Description   Mr. Frog has an integer sequence of length n, which can be denoted ...

  2. HDU 5919 Sequence II(主席树+逆序思想)

    Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) To ...

  3. HDU 5919 -- Sequence II (主席树)

    题意: 给一串数字,每个数字的位置是这个数第一次出现的位置. 每个询问对于序列的一个子区间,设一共有k个不同的数,求第ceil(k/2)个数的位置. 因为强制在线,所以离线乱搞pass掉. 主席树可解 ...

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

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

  5. hdu 5919 Sequence II (可持久化线段树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919 大致题意: 给你一个长度为n的序列,q个询问,每次询问是给你两个数x,y,经过与上一次的答案进行运算 ...

  6. HDU5919 Sequence II(主席树)

    Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,⋯,ana1,a2,⋯,anThere are ...

  7. HDU - 5919 Sequence II

    题意: 给定长度为n的序列和q次询问.每次询问给出一个区间(L,R),求出区间内每个数第一次出现位置的中位数,强制在线. 题解: 用主席树从右向左的插入点.对于当前点i,如果a[i]出现过,则把原位置 ...

  8. hdu 5147 Sequence II【树状数组/线段树】

    Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...

  9. HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5919 题意:给出一串序列,每次给出区间,求出该区间内不同数的个数k和第一个数出现的位置(将这些位置组 ...

随机推荐

  1. Jmeter跨线程组传递参数

    Jmeter的线程组之间是相互独立的,各个线程组互不影响,所以线程组A中输出的参数,是无法直接在线程组B中被调用的. 但有时候为了方便,可以把不同模块接口放在不同线程组,就涉及不同线程组传参问题,比如 ...

  2. jmeter 之调试

    目前知道的调试方法有两种:debug sample .http mirror server debug sample  debug sample 的用户界面如下: 如果选择ture则表示打印对应的数据 ...

  3. Linux-centos7下python3 环境设置

    首先安装依赖包 yum -y groupinstall "Development tools" yum -y install zlib-devel bzip2-devel open ...

  4. angular脚手架搭建

    下面以angular2.0为例前提已安装好node.js 1.安装cli执行如下命令npm install -g @angular/cli 2.创建新项目ng new my-app 3.然后到该项目目 ...

  5. vue-cli +echarts-amap集成echarts和高德地图TypeError: Cannot read property 'dataToPoint' of null解决方案

    由于项目的需求,需要做一种迁徙效果, 最后我们采用了组件化开发,可以说这个坑自己一个人踩,有点累,但也收获不少. vue-cli +echarts-amap集成echarts和高德地图,出现报错,错误 ...

  6. pyothon学习笔记2-元组

    # 1.元组对象不可修改,元组中列表对象的对象可以修改 t = (1,2,[1,2,3]) t[2] = [1,2,3,4] # 'tuple' object does not support ite ...

  7. mac配置自带vim高亮显示

    查找/etc/.vimrc的内容,如果没有的话 新建~/vimrc文件,在文件中写入如下内容即可 set ai " auto indenting set history=100 " ...

  8. PowerBI/Excel - PowerQuery数据转换系列 - 如何将多行的值串联到一行 - 行列转换

    Power Query 是做数据转换.数据清洗的利器,不管是在Excel还是PowerBI,如何玩好Power Query是成功建模的必不可少的一步. 今天要get到的一个新技巧:行列转换 如何将多行 ...

  9. adobe air for ios 应用完成appstore评论

    1,跳转到App Store:NSString *str = [NSString stringWithFormat:@"http://itunes.apple.com/us/app/id%d ...

  10. 18. C# 转换

    1.重载转换运算符 到目前为止,我们使用的类型转换,包括隐式类型转换和显示类型转换都是在两个相关的类中进行的,这几个类要么是简单类型之间的转换,比如int 隐式转换成double,要么是有继承关系,或 ...