2016 ccpc长春现场赛J Sequence II(hdu 5919)

来源:互联网 发布:网络红人欲猫儿 编辑:程序博客网 时间:2024/04/29 10:41


Sequence II

Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 466    Accepted Submission(s): 112


Problem Description
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 ali,ali+1,ali+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)ki (in ascending order, i.e.,p(i)1<p(i)2<<p(i)ki).

Note that ki is the number of different integers in this subsequence. You should output p(i)ki2for the i-th query.
 

Input
In the first line of input, there is an integer T (T2) denoting the number of test cases.

Each test case starts with two integers n (n2×105) and m (m2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,,an,0ai2×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 li,ri(1lin,1rin). 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 li,ri)by the following formula:
li=min{(li+ansi1) mod n+1,(ri+ansi1) mod n+1}

ri=max{(li+ansi1) mod n+1,(ri+ansi1) mod n+1}
 

Output
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.
 

Sample Input
25 23 3 1 5 42 24 45 22 5 2 1 22 32 4
 

Sample Output
Case #1: 3 3Case #2: 3 1
Hint
 

Source
2016中国大学生程序设计竞赛(长春)-重现赛
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5921 5920 5918 5917 5916 
题意:给你一个序列,k表示某区间一共有几个不同的数,然后求区间第(k+1)/2次出现的数的位置。

思路:现场赛的时候因为对主席树的结构不清楚,队友说有模板可以求区间不同数的个数,然后就想着套二分结果时间不够没能提交,后来重现的时候试了一发原来mlogn^2也过不了,然后研究了一下主席树的结构就发现了mlogn*2的做法,下面给代码:

#include<set>#include<map>#include<ctime>#include<cmath>#include<stack>#include<queue>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>#include<functional>typedef long long LL;using namespace std;#define inf 0x3f3f3f3f#define maxn 200005typedef long long LL;int n, m;int a[maxn], root[maxn];int data[maxn * 40], ls[maxn * 40], rs[maxn * 40];int cnt;map<int, int> mp;const int read(){char ch = getchar();while (ch<'0' || ch>'9') ch = getchar();int x = ch - '0';while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';return x;}int build(int l, int r){int t = cnt++;data[t] = 0;if (l == r)return t;int mid = (l + r) >> 1;ls[t] = build(l, mid);rs[t] = build(mid + 1, r);return t;}int update(int p, int l, int r, int v, int w){int t = cnt++;data[t] = data[p] + w;if (l == r) return t;int mid = (l + r) >> 1;if (v <= mid){rs[t] = rs[p];ls[t] = update(ls[p], l, mid, v, w);}else{ls[t] = ls[p];rs[t] = update(rs[p], mid + 1, r, v, w);}return t;}int query(int t, int l, int r, int v){if (l == r)return data[t];int mid = (l + r) >> 1;if (v > mid)return query(rs[t], mid+1, r, v) + data[ls[t]];else return query(ls[t], l, mid, v);}int dfs(int t, int l, int r,int value){if (l == r)return l;int mid = (l + r) >> 1;if (data[ls[t]] >= value)return dfs(ls[t], l, mid, value);elsereturn dfs(rs[t], mid + 1, r, value-data[ls[t]]);}int main(){int t;scanf("%d", &t);for (int tcase = 1; tcase <= t; tcase++){scanf("%d%d", &n, &m);cnt = 1; mp.clear();for (int i = 1; i <= n; i++){a[i] = read();}root[n + 1] = build(1, n);for (int i = n; i; i--){if (mp[a[i]] == 0)root[i] = update(root[i + 1], 1, n, i, 1);else {int tmp = update(root[i + 1], 1, n, mp[a[i]], -1);root[i] = update(tmp, 1, n, i, 1);}mp[a[i]] = i;}int ans = 0;printf("Case #%d:", tcase);while(m--){int l, r;l = read();r = read();int ll = ((l + ans) % n) + 1;int rr = ((r + ans) % n) + 1;int l0 = min(ll, rr);int r0 = max(ll, rr);int k = query(root[l0], 1, n, r0);k = (k + 1) >> 1;ans = dfs(root[l0], 1, n,  k);printf(" %d", ans);}printf("\n");}}


0 0
原创粉丝点击