HDU 5919 Sequence II

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919

------------------------------------------------------------------------------------

现场赛的时候由于不会主席树就用分块卡过去了

现在学习了主席树后感觉这题也是很有意思的

首先 这题要把问题转化为对于一段区间 求一个左端点相同的$($如果有多个取右端点最靠左的$)$子区间

这个子区间的不同数的个数等于原区间不同数的个数除二向上取整

求区间不同数个数是主席树模板题之一 建议先做完下面这题再来看

http://www.cnblogs.com/sagitta/p/5937253.html

对于这题 由于不是求一个给定区间不同数的个数 看起来似乎还需要对子区间右端点进行二分才行

如果真的按照这种思路就是$O(Nlog^{2}N)$了 虽然此题也不卡这种解法

但是考虑到有不少线段树$/ST$表$/$倍增 再加一个二分的题目实际操作中并不需要在外层套一个二分

因此这里我们也可以试着看看能否直接利用线段树维护的区间上的信息来免去二分

再对问题进行观察 我们发现要求的子区间与原区间的左端点是一样的 即子区间左端点是固定的

因此我们可以考虑在主席树上维护后缀区间而不是前缀区间

维护后缀区间的话 我们只需在主席树上每次对左右区间进行判断到底往那个区间走就行$($逐步确定右端点位置$)$

这样就是$O(NlogN)$的了

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int N = 2e5 + 10, T = N * 40;
  4 int sum[T], ch[T][2], root[N << 1], ma[N], last[N];
  5 int a[N];
  6 int croot, cnt, n, q;
  7 int build(int x, int L, int R)
  8 {
  9     if(L == R)
 10     {
 11         sum[x] = 0;
 12         return x;
 13     }
 14     int mid = (L + R) >> 1;
 15     ch[x][0] = build(++cnt, L, mid);
 16     ch[x][1] = build(++cnt, mid + 1, R);
 17     sum[x] = sum[ch[x][0]] + sum[ch[x][1]];
 18     return x;
 19 }
 20 int update(int x, int L, int R, int y, int delta, int pre)
 21 {
 22     if(L == R)
 23     {
 24         sum[x] = sum[pre] + delta;
 25         return x;
 26     }
 27     int mid = (L + R) >> 1;
 28     if(y <= mid)
 29     {
 30         ch[x][0] = update(++cnt, L, mid, y, delta, ch[pre][0]);
 31         ch[x][1] = ch[pre][1];
 32     }
 33     else
 34     {
 35         ch[x][0] = ch[pre][0];
 36         ch[x][1] = update(++cnt, mid + 1, R, y, delta, ch[pre][1]);
 37     }
 38     sum[x] = sum[ch[x][0]] + sum[ch[x][1]];
 39     return x;
 40 }
 41 int query(int x, int L, int R, int r)
 42 {
 43     if(R <= r)
 44         return sum[x];
 45     int mid = (L + R) >> 1;
 46     if(r <= mid)
 47         return query(ch[x][0], L, mid, r);
 48     return sum[ch[x][0]] + query(ch[x][1], mid + 1, R, r);
 49 }
 50 int findkth(int x, int L, int R, int k)
 51 {
 52     if(L == R)
 53         return L;
 54     int mid = (L + R) >> 1;
 55     if(k <= sum[ch[x][0]])
 56         return findkth(ch[x][0], L, mid, k);
 57     else
 58         return findkth(ch[x][1], mid + 1, R, k - sum[ch[x][0]]);
 59 }
 60 int t;
 61 int main()
 62 {
 63     scanf("%d", &t);
 64     for(int ca = 1; ca <= t; ++ca)
 65     {
 66         croot = cnt = 0;
 67         memset(last, 0, sizeof last);
 68         scanf("%d%d", &n, &q);
 69         root[++croot] = ++cnt;
 70         ma[0] = 1;
 71         build(cnt, 1, n);
 72         for(int i = 1; i <= n; ++i)
 73             scanf("%d", &a[i]);
 74         for(int i = n; i; --i)
 75         {
 76             ++croot;
 77             root[croot] = update(++cnt, 1, n, i, 1, root[croot - 1]);
 78             if(last[a[i]])
 79             {
 80                 ++croot;
 81                 root[croot] = update(++cnt, 1, n, last[a[i]], -1, root[croot - 1]);
 82             }
 83             last[a[i]] = i;
 84             ma[i] = root[croot];
 85         }
 86         printf("Case #%d:", ca);
 87         int ans = 0, l, r, x, y;
 88         while(q--)
 89         {
 90             scanf("%d%d", &x, &y);
 91             l = min((x + ans) % n + 1, (y + ans) % n + 1);
 92             r = max((x + ans) % n + 1, (y + ans) % n + 1);
 93             int cnt = query(ma[l], 1, n, r);
 94             ans = findkth(ma[l], 1, n, (cnt + 1) / 2);
 95             printf(" %d", ans);
 96         }
 97         puts("");
 98     }
 99     return 0;
100 }
时间: 2024-10-12 11:52:09

HDU 5919 Sequence II的相关文章

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

Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1422    Accepted Submission(s): 362 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2

HDU 5919 Sequence II 主席树

Sequence II 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 deno

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

HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2那个. 思路: 主席树操作,这里的思路是从n到1开始建树.其他就是主席树查询区间第K小,计算区间不同值个数. #include <algorithm> #include <iterator> #include <iostream> #include <cstring&

HDU 5919 -- Sequence II (主席树)

题意: 给一串数字,每个数字的位置是这个数第一次出现的位置. 每个询问对于序列的一个子区间,设一共有k个不同的数,求第ceil(k/2)个数的位置. 因为强制在线,所以离线乱搞pass掉. 主席树可解. 考虑一个数列: p      1 2 3 4 5 6  // 原序列标号 a : 1 2 1 2 3 4  // 原序列 p1 1 2 1 2 5 6  // 子序列开始下标为1 p2        2 3 1 5 6 p3           3 4 5 6 p4              4

HDU 5919 Sequence II(主席树)题解

题意:有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个不同的数字下标是多少? 思路:显然是个在线询问. 我们之前已经会用主席树求区间内有多少不同数字了:从左到右把每个数字的位置存进每个操

hdu 5147 Sequence II(树状数组)

题目链接:hdu 5147 Sequence II 预处理每个位置作为b和c可以组成的对数,然后枚举b的位置计算. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 50005; int N, arr[maxn], fenw[maxn], lef[maxn], rig[maxn]; #d

hdu 5147 Sequence II (树状数组 求逆序数)

题目链接 Sequence II Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 331    Accepted Submission(s): 151 Problem Description Long long ago, there is a sequence A with length n. All numbers in this se

[ACM] hdu 5147 Sequence II (树状数组,前缀和,后缀和)

Sequence II Problem Description Long long ago, there is a sequence A with length n. All numbers in this sequence is no smaller than 1 and no bigger than n, and all numbers are different in this sequence. Please calculate how many quad (a,b,c,d) satis

hdu 5147 Sequence II

http://acm.hdu.edu.cn/showproblem.php?pid=5147 题意:问有多少个这样的四元组(a,b,c,d),满足条件是 1<=a<b<c<d; Aa<Ab; Ac<Ad; 思路:用树状数组求,从右向左求在这个数之前形成多少个逆序数对记录在r数组里面,然后在从左向右求出在输入这个数之前形成多少个逆序数对存在l数组里面,然后枚举b就行: 1 #include <cstdio> 2 #include <cstring>