[HDU5919]Sequence II
[HDU5919]Sequence II
试题描述
Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,⋯,an There are m queries.
In the i-th query, you are given two integers li and ri. Consider the subsequence al_i,al_(i+1),al_(i+2),⋯,ari.
We can denote the positions(the positions according to the original sequence) where an integer appears first in this subsequence as p(i)1,p(i)2,⋯,p(i)k_i (in ascending order, i.e.,p(i)1<p(i)2<⋯<p(i)k_i).
Note that ki is the number of different integers in this subsequence. You should output p(i)⌈ki/2⌉for the i-th query.
In the i-th query, you are given two integers li and ri. Consider the subsequence al_i,al_(i+1),al_(i+2),⋯,ari.
We can denote the positions(the positions according to the original sequence) where an integer appears first in this subsequence as p(i)1,p(i)2,⋯,p(i)k_i (in ascending order, i.e.,p(i)1<p(i)2<⋯<p(i)k_i).
Note that ki is the number of different integers in this subsequence. You should output p(i)⌈ki/2⌉for the i-th query.
输入
In the first line of input, there is an integer T (T≤2) denoting the number of test cases.
Each test case starts with two integers n (n≤2×105) and m (m≤2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,⋯,an,0≤ai≤2×105).
There are two integers li and ri in the following m lines.
However, Mr. Frog thought that this problem was too young too simple so he became angry. He modified each query to l‘i,r‘i(1≤l‘i≤n,1≤r‘i≤n). As a result, the problem became more exciting.
We can denote the answers as ans1,ans2,⋯,ansm. Note that for each test case ans0=0.
You can get the correct input li,ri from what you read (we denote them as l‘i,r‘i)by the following formula:
Each test case starts with two integers n (n≤2×105) and m (m≤2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,⋯,an,0≤ai≤2×105).
There are two integers li and ri in the following m lines.
However, Mr. Frog thought that this problem was too young too simple so he became angry. He modified each query to l‘i,r‘i(1≤l‘i≤n,1≤r‘i≤n). As a result, the problem became more exciting.
We can denote the answers as ans1,ans2,⋯,ansm. Note that for each test case ans0=0.
You can get the correct input li,ri from what you read (we denote them as l‘i,r‘i)by the following formula:
li=min{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1}
ri=max{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1}
输出
You should output one single line for each test case.
For each test case, output one line “Case #x: p1,p2,⋯,pm”, where x is the case number (starting from 1) and p1,p2,⋯,pm is the answer.
输入示例
2 5 2 3 3 1 5 4 2 2 4 4 5 2 2 5 2 1 2 2 3 2 4
输出示例
Case #1: 3 3 Case #2: 3 1
数据规模及约定
见“输入”
题解
就是这道题再强行套一个二分。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); } return x * f; } #define maxn 200010 #define maxnode 4000010 int ToT, sumv[maxnode], lc[maxnode], rc[maxnode]; void update(int& y, int x, int l, int r, int p) { sumv[y = ++ToT] = sumv[x] + 1; if(l == r) return ; int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x]; if(p <= mid) update(lc[y], lc[x], l, mid, p); else update(rc[y], rc[x], mid + 1, r, p); return ; } int query(int o, int l, int r, int qr) { if(!o) return 0; if(r <= qr) return sumv[o]; int mid = l + r >> 1, ans = query(lc[o], l, mid, qr); if(qr > mid) ans += query(rc[o], mid + 1, r, qr); return ans; } int rt[maxn], lstp[maxn], ANS[maxn], cnt; int len; char Out[maxn*7]; int main() { int T = read(); for(int kase = 1; kase <= T; kase++) { memset(lstp, 0, sizeof(lstp)); memset(sumv, 0, sizeof(sumv)); memset(lc, 0, sizeof(lc)); memset(rc, 0, sizeof(rc)); memset(rt, 0, sizeof(rt)); ToT = 0; int n = read(), q = read(); for(int i = 1; i <= n; i++) { int v = read(); update(rt[i], rt[i-1], 0, n, lstp[v]); lstp[v] = i; } cnt = 0; int lst = 0; while(q--) { int ql = (read() + lst) % n + 1, qr = (read() + lst) % n + 1; if(ql > qr) swap(ql, qr); int l = ql, r = qr, k = query(rt[qr], 0, n, ql - 1) - query(rt[ql-1], 0, n, ql - 1) + 1 >> 1, lval = query(rt[ql-1], 0, n, ql - 1); while(l < r) { int mid = l + r >> 1; if(query(rt[mid], 0, n, ql - 1) - lval < k) l = mid + 1; else r = mid; } ANS[++cnt] = lst = l; } printf("Case #%d: ", kase); len = 0; int num[10], cntn; for(int i = 1; i <= cnt; i++) { int tmp = ANS[i]; if(!tmp) Out[len++] = '0'; cntn = 0; while(tmp) num[++cntn] = tmp % 10, tmp /= 10; for(int j = cntn; j; j--) Out[len++] = num[j] + '0'; if(i < cnt) Out[len++] = ' '; } Out[len] = '\0'; puts(Out); } return 0; }