hdu_5919_Sequence II(主席树)

题目链接:hdu_5919_Sequence II

题意:

给你n个数,m个询问,每次问你一个区间中每一种数在区间中第一次出现的位置的中位数,强制在线。

题解:

一看就是主席树搞,不过这里要询问第一次出现的位置,有个技巧就是倒着将数插进去,如果有相同的数,就把位置靠后的数的贡献取消掉,这样查询的时候就只需要查询root[l]了,因为root[l]包括了l到n的信息,前面已经只保留了相同数的最前面的位置,所以查询一共有多少种数时直接查询root[l]的l到r就行了。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4
 5 const int N=2e5+7;
 6 struct node{int l,r,sum;}T[40*N];
 7
 8 int t,n,m,a[N],pre[N],root[N],tot,ic=1;
 9
10 void update(int &x,int y,int pos,int val,int l=1,int r=n)
11 {
12     T[++tot]=x?T[x]:T[y],T[tot].sum+=val,x=tot;
13     if(l==r)return;
14     int m=l+r>>1;
15     if(pos<=m)update(T[x].l,T[y].l,pos,val,l,m);
16     else update(T[x].r,T[y].r,pos,val,m+1,r);
17 }
18
19 int query(int x,int k,int l=1,int r=n)
20 {
21     if(l==r)return l;
22     int m=l+r>>1;
23     if(k<=T[T[x].l].sum)return query(T[x].l,k,l,m);
24     return query(T[x].r,k-T[T[x].l].sum,m+1,r);
25 }
26
27 int getsum(int x,int L,int R,int l=1,int r=n)
28 {
29     if(L<=l&&r<=R)return T[x].sum;
30     int m=l+r>>1,ans=0;
31     if(L<=m)ans+=getsum(T[x].l,L,R,l,m);
32     if(R>m)ans+=getsum(T[x].r,L,R,m+1,r);
33     return ans;
34 }
35
36 int main()
37 {
38     scanf("%d",&t);
39     while(t--)
40     {
41         printf("Case #%d: ",ic++);
42         scanf("%d%d",&n,&m);
43         tot=0;
44         F(i,1,n)scanf("%d",a+i);
45         for(int i=n;i>0;i--)
46         {
47             if(pre[a[i]])update(root[i],root[i+1],pre[a[i]],-1);
48             update(root[i],root[i+1],i,1);
49             pre[a[i]]=i;
50         }
51         int ans=0,l,r,sum;
52         F(i,1,m)
53         {
54             scanf("%d%d",&l,&r);
55             l=(l+ans)%n+1,r=(r+ans)%n+1;
56             if(l>r)l^=r,r^=l,l^=r;
57             sum=getsum(root[l],l,r);
58             printf("%d%c",ans=query(root[l],sum+1>>1)," \n"[i==m]);
59         }
60         while(tot)T[tot].l=T[tot].r=T[tot].sum=0,tot--;
61         F(i,1,n)root[i]=0,pre[a[i]]=0;
62     }
63     return 0;
64 }

时间: 2024-11-04 22:39:03

hdu_5919_Sequence II(主席树)的相关文章

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 (主席树)

题意: 给一串数字,每个数字的位置是这个数第一次出现的位置. 每个询问对于序列的一个子区间,设一共有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 (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

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

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

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include

【poj1901-求区间第k大值(带修改)】树状数组套主席树

901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7025  Solved: 2925[Submit][Status][Discuss] Description 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]

hdu 5919 主席树(区间不同数的个数 + 区间第k大)

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

动态主席树 优化版

和大奕哥一起学习了主席树,机房里杰哥看了之后一直说可以优化空间,题解写的太low了,所以我今天写了一个动态开点的线段树来优化一波空间,bz上试了一下,确实比网上看的题解省空间. 网上的题解是每一次都新开点,是可持久化的写法,我写的是正经的线段树动态开点. 附上代码 #include<bits/stdc++.h> using namespace std; const int N=10010,INF=1e9+10; int n,m,pl,tl,mx; int a[N<<1],num[N

Dynamic Ranking(主席树,树套树,树状数组)

洛谷题目传送门 YCB巨佬对此题有详细的讲解.%YCB%请点这里 思路分析 不能套用静态主席树的方法了.因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍...... 话说我真的快要忘了有一种数据结构,能支持单点修改,区间查询,更重要的是,常数优秀的它专门用来高效维护前缀和!!它就是-- !树状数组! 之前静态主席树要保存的每个线段树\([1,i]\),不也是一个庞大的前缀吗?于是,把树状数组套在线段树上,构成支持动态修改的主席树.每个树状数组的节点即为一个线段树的根节点