HDU 5919 Sequence II 主席树
2016-10-05 23:13
381 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5919Sequence II
Time Limit: 9000/4500 MS (Java/Others)Memory Limit: 131072/131072 K (Java/Others)问题描述
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)⌈ki2⌉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:
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
题意
求区间[l,r]的所有不重复的数(重复的以第一次出现的位置为准)位于中间(位置在中间,不是值)那个数所在的位置。
题目强制在线
题解
用主席树,倒过来建树,从第n个位置建到第1个位置,对于重复的数边做边删,保证只留在最左边的那个,然后对于查询[l,r],我们去查rt[l]那棵树的l,r区间,得到不重复的数有cnt个,然后用求区间第k大的办法去求第(cnt+1)/2大的数。
还有一种思路,每个数存它前驱的位置,然后用主席树求区间[l,r]中比l小的数的个数,从而可以求区间[l,r]内不同的数的个数,然后二分t,去找中间的位置, 这样的复杂度是
nlogn+q*logn*logn,会卡时间,反正我是t了。
代码
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<sstream> using namespace std; #define X first #define Y second #define mkp make_pair #define mid (l+(r-l)/2) #define lson(o) (tre[(o)].ls) #define rson(o) (tre[(o)].rs) #define sumv(o) (tre[(o)].sum) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=0x3f3f3f3f3f3f3f3fLL; const double eps=1e-8; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=201010; ///nlogn空间复杂度 ///注意:由于有增加和删除两个操作!所以空间是2n*log(2n) struct Tre { int ls,rs,sum; Tre() { ls=rs=sum=0; } } tre[maxn*50]; int n,m; int rt[maxn],tot; int _v,_p; void update(int &o,int l,int r) { tre[++tot]=tre[o],o=tot; if(l==r) { sumv(o)+=_v; } else { if(_p<=mid) update(lson(o),l,mid); else update(rson(o),mid+1,r); sumv(o)=sumv(lson(o))+sumv(rson(o)); } } ///区间内不同的数有几个 int _res,ql,qr; void query(int o,int l,int r) { if(ql<=l&&r<=qr) { _res+=sumv(o); } else { if(ql<=mid) query(lson(o),l,mid); if(qr>mid) query(rson(o),mid+1,r); } } ///区间第k大 int _res2; void query2(int o,int l,int r,int k) { if(l==r) { _res2=l; } else { if(k<=sumv(lson(o))) query2(lson(o),l,mid,k); else query2(rson(o),mid+1,r,k-sumv(lson(o))); } } int arr[maxn],mp[maxn]; ///0是个超级节点 void init() { rt[n+1]=tot=0; } int main() { int tc,kase=0; scf("%d",&tc); while(tc--) { scf("%d%d",&n,&m); init(); for(int i=1; i<=n; i++) { scf("%d",&arr[i]); } ///主席树 for(int i=1; i<=n; i++) mp[i]=n+1; for(int i=n; i>=1; i--) { rt[i]=rt[i+1]; _v=1,_p=i; update(rt[i],1,n); if(mp[arr[i]]<=n) { _v=-1,_p=mp[arr[i]]; update(rt[i],1,n); } mp[arr[i]]=i; } int ans=0; VI lis; while(m--) { int ll,rr; scf("%d%d",&ll,&rr); int t1=(ll+ans)%n+1,t2=(rr+ans)%n+1; int l=min(t1,t2),r=max(t1,t2); ///求区间内不同的数有几个 ql=l,qr=r,_res=0; query(rt[l],1,n); int k=(_res+1)/2; ///求区间第k大 query2(rt[l],1,n,k); ans=_res2; lis.pb(ans); } prf("Case #%d:",++kase); rep(i,0,lis.sz()) { prf(" %d",lis[i]); } putchar('\n'); } return 0; } //end-----------------------------------------------------------------------
相关文章推荐
- [hdu 5919 Sequence II] 主席树
- hdu 5919 Sequence II (主席树,求区间不同数的个数)
- hdu 5919 Sequence II 主席树
- HDU 5919 Sequence II 【主席树】
- HDU 5919 Sequence II [主席树]【数据结构】
- HDU 5919 Sequence II(主席树)
- HDU 5919 Sequence II (主席树,不同元素个数+第K大)
- HDU 5919-Sequence II(主席树)
- hdu 5919 Sequence II(主席树,求区间不同数的个数)
- hdu5919 Sequence II(主席树,区间第k大)
- [HDU 5919] Sequence II (主席树)
- Hdu-5919 Sequence II(主席树在线求区间不同数)
- hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)
- HDU 5919 Sequence II 主席树
- hdu_5919_Sequence II(主席树)
- hdu5919 Sequence II(主席树求区间数种数和k大查找)
- HDU 5919 Sequence II 主席树
- HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)
- HDU 5919 Sequence II 主席树
- hdu 5919 Sequence II(主席树)