题意:有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. Elasticsearch学习笔记(十)批量查询mget、批量增删改bulk

    一.批量查询  mget             GET /_mget {   "docs":[       {         "_index":" ...

  2. Django中cookie和session使用

    cookie和session的简单使用 def cookie(request): """ 操作cookie """ resp = HttpR ...

  3. numpy(四)

    逻辑符 : ==  !=  <  > <=  >= x=np.array([1,3,5]) x<3 array([True,False,,False]) (2*x) == ...

  4. FEX(Fabric Extender)

    一.FEX Cisco Nexus 2000 FEX作为N5K.N6K.N7K.FI的一个远程线卡,单独的2K是没有网管功能的,必须配合父系交换机使用. 主要解决TOR和EOR的问题,TOR,接线简单 ...

  5. zblog如何更改数据库配置以及生效

    zblog是一个博客的开源框架, 挺不错的,我们当前拿来作为新闻系统管理使用. 由于我们数据库需要统一使用RDS, 故对zblog数据库配置进行修改,修改文件如下: 1. 数据库文件地址: zb_us ...

  6. 【Docker】-NO.132.Docker.1 -【Docker 修改容器端口】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  7. LeetCode 5 最长对称串

    LeetCode 5 最长对称串 最早时候做这道题的时候还是用Java写的,用的是字符串匹配的思路,一直Time Limit Exceeded.甚至还想过用KMP开优化子串查找. public cla ...

  8. mac pro换屏指南

    https://www.ifixit.com/ 该网站提供了 换屏的详细操作步骤.

  9. 白话skynet第二篇:skynet的通信调试pack和sprotol

    今天来说说Skynet客户端和服务端网络通信的基础部分. Skynet当前版本.lua是skynet自带的5.3版本. 根据示例,我们可以知道.通信的步骤如下. 客户端按大小端打包成二进制. sock ...

  10. 在C#中,Newtonsoft.Json + dynamic动态解析jsonString,jsonString转实体

    记录一下 引用 using Newtonsoft.Json; using Newtonsoft.Json.Linq; var jsonString = "{\"ApiResourc ...