hdu 5919 Sequence II (可持久化线段树)
来源:互联网 发布:三大男高音 知乎 编辑:程序博客网 时间:2024/05/16 12:34
题意:
题目传送门
由于是英文题,我直接说题目大意。
给出一个拥有不超过2*10^5个元素的序列,再给出2*10^5个询问,对于每一个询问[L,R],我们假设区间内有k个不同的数,他们在这个区间内第一次出现的位置分别为p1,p2,p3……pk,排序后输出第(k/2向上取整)个数。本题采用强制在线。
举个栗子:1 1 2 3 3,询问区间为[2,5]。
我们发现区间内有3个不同的数,他们在区间内第一次出现的位置为:
1 2
2 3
3 4
(这里的位置是指在原序列中的位置)
于是输出3(以上引自某神犇博客,谁叫我的英文水平很差=。=)
分析:
这题类似之前我写的博客中的HH的项链那道题,那道题是这题的简化版(不知道主席树怎么写或不知道一个区间中有几个不同的数怎么求可参见那篇博客)
于是我们类比那题,发现此题只多了一次二叉查找,即找第[k/2]个位置。由于保留第一次出现的位置,我们从后往前做。做到L的时候我们查询[L,R]的和并记为k,即[L, R]中有k个不同的数,然后再用一次二叉查找(位置已有序)找到中间那个数的位置。至于强制在线,用可持久化即可。
ps:注意空间大小和输出格式
代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#define N 200005using namespace std;int T, n, m, cur; int p[N], Ans[N], Next[N];struct Tnode{ Tnode *lson, *rson; int sum;}tree[N*35], *Root[N];Tnode *NewTnode(){ tree[cur].lson = tree[cur].rson = tree; tree[cur].sum = 0; return tree+cur++;}void update(Tnode *root, int L, int R, int x, int val){ if(L == x && x == R){ root->sum += val; return; } int mid = (L + R) >> 1; Tnode *p = NewTnode(); if(x <= mid){ *p = *root->lson; root->lson = p; update(p, L, mid, x, val); } else{ *p = *root->rson; root->rson = p; update(p, mid+1, R, x, val); } root->sum = root->lson->sum + root->rson->sum;}int query(Tnode *root, int L, int R, int x, int y){ if(x > R || y < L) return 0; if(x <= L && y >= R) return root->sum; int mid = (L + R) >> 1; int tmp1 = query(root->lson, L, mid, x, y); int tmp2 = query(root->rson, mid+1, R, x, y); return tmp1 + tmp2;}int Find(Tnode *root, int L, int R, int rank){ if(L == R) return L; int mid = (L + R) >> 1, lsum = root->lson->sum; if(rank <= lsum) Find(root->lson, L, mid, rank); else Find(root->rson, mid+1, R, rank-lsum);}int main(){ scanf("%d", &T); for(int C = 1; C <= T; C++){ scanf("%d%d", &n, &m); cur = 0; Root[n+1] = NewTnode(); memset(Next, -1, sizeof(Next)); for(int i = 1; i <= n; i++) scanf("%d", &p[i]); for(int i = n; i > 0; i--){ Root[i] = NewTnode(); *Root[i] = *Root[i+1]; if(~ Next[p[i]]) update(Root[i], 1, n, Next[p[i]], -1); Next[p[i]] = i; update(Root[i], 1, n, i, 1); } int a, b, lastans = 0; Ans[0] = 0; for(int i = 1; i <= m; i++){ scanf("%d%d", &a, &b); a = (a + lastans) % n + 1; b = (b + lastans) % n + 1; if(a > b) swap(a, b); int k = query(Root[a], 1, n, a, b); k = (k + 1) >> 1; lastans = Find(Root[a], 1, n, k); Ans[++Ans[0]] = lastans; } printf("Case #%d: ", C); for(int i = 1; i <= Ans[0]; i++){ printf("%d", Ans[i]); if(i != Ans[0]) printf(" "); } printf("\n"); } return 0;}
“告诉我花是红色的人是你,告诉我世界是五彩斑斓的人也是你。” ——《人渣的本愿》
1 0
- hdu 5919 Sequence II (可持久化线段树)
- hdu5919:Sequence II(可持久化线段树)
- hdu 4348 可持久化线段树
- *hdu 2665 (可持久化线段树)
- hdu 5820 可持久化线段树
- hdu 2665 Kth number ( 可持久化线段树 )
- 【HDU 4348】To the moon【可持久化线段树】
- 【可持久化线段树】【hdu 4348】To the moon
- 【HDU】4348 To the moon 【可持久化线段树】
- HDU 2665 Kth number 可持久化线段树
- hdu 4348 可持久化线段树(区间和
- HDU-2665 Kth number (可持久化线段树)
- Hdu-4348 To the moon(可持久化线段树)
- Hdu-5438 Boring counting(可持久化线段树)
- HDU 3333 Turing Tree 可持久化线段树
- HDU 2665 Kth number 可持久化线段树
- 可持久化线段树
- 可持久化线段树
- 光照综述
- 保存/恢复 Activity 和 Fragment 状态的最佳实
- [深度学习] Batch Normalization算法介绍
- 【Linux】进程终止以及atexit()函数的介绍
- C++ STL中Map的按Key排序和按Value排序
- hdu 5919 Sequence II (可持久化线段树)
- POI读取Excel
- linux系统记录用户操作实现方法
- Swift
- 名不副实的getchar()
- dubbo简单集成spring
- 线程安全
- J2EE系列之Struts2学习笔记(四)---使用javabean方式给类对象赋值
- WPF 选择treeview子节点获取父节点