题意
给出一个序列,问区间[l, r]中所有不同元素出现的第一个位置(取最左)组成的序列中的中位数。
题解
如果我们从后往前的话在当前位置i我们在主席树上i这个位置加1,在它之前出现的位置减1,然后我们在主席树询问区间的时候每个数都只出现一次了。
查询[l, r]的时候,查询第l个版本的主席树就好,复杂度O(nlogn)。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <string.h>
#include <string>
#include <queue>
#include <set>
using namespace std;
//ios_base::sync_with_stdio(false);
//#include <bits/stdc++.h>
typedef long long ll;
#define maxn 200010
int root[maxn], tot;
struct seg {
int lson, rson, val;
} T[maxn * 40];
void update(int l, int r, int &now, int pre, int i, int val)
{
int tmp = now;
now = ++tot;
T[now] = tmp ? T[tmp] : T[pre];
T[now].val += val;
if(l == r) return ;
int m = (l + r) >> 1;
if(i <= m) update(l, m, T[now].lson, T[pre].lson, i, val);
else update(m + 1, r, T[now].rson, T[pre].rson, i, val);
}
int query(int l, int r, int now, int K)
{
if(l == r) return r;
int m = (l + r) >> 1;
if(T[T[now].lson].val >= K)
return query(l, m, T[now].lson, K);
else
return query(m + 1, r, T[now].rson, K - T[T[now].lson].val);
}
int getsum(int l, int r, int now, int L, int R)
{
if(L <= l && r <= R) return T[now].val;
int m = (l + r) >> 1, ret = 0;
if(L <= m) ret += getsum(l, m, T[now].lson, L, R);
if(R > m) ret += getsum(m + 1, r, T[now].rson, L, R);
return ret;
}
int a[maxn], p[maxn], ans[maxn];
int main()
{
int t, kase = 0;
cin >> t;
while(t--)
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = n; i >= 1; i--)
{
if(p[a[i]]) update(1, n, root[i], root[i+1], p[a[i]], -1);
update(1, n, root[i], root[i+1], i, 1);
p[a[i]] = i;
}
ans[0] = 0;
for(int i = 0, l, r, sum; i < m; i++)
{
if(i)
ans[i] = ans[i-1];
scanf("%d%d", &l, &r);
l = (l + ans[i]) % n + 1;
r = (r + ans[i]) % n + 1;
if(l > r) swap(l, r);
sum = getsum(1, n, root[l], l, r);
sum = sum / 2 + sum % 2;
ans[i] = query(1, n, root[l], sum);
}
printf("Case #%d:", ++kase);
for(int i = 0; i < m; i++)
printf(" %d", ans[i]);
printf("\n");
while(tot)
{
T[tot].lson = T[tot].rson = 0;
T[tot--].val = 0;
}
for(int i = 1; i <= n; i++)
{
root[i] = 0;
p[a[i]] = 0;
}
tot = 0;
}
return 0;
}