HDU5919 SequenceⅡ

从后向前建主席树,以位置为下标建树,然后查询区间出现次数的第k/2大即可。

复杂度O(nlogn)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=2e5+10;
 4 int num,ans[N],T,pre[N],rt[N],a[N];
 5 struct node
 6 {
 7     int s,l,r;
 8 }t[N*36];
 9 void init()
10 {
11     memset(rt,0,sizeof(rt));num=0;
12     memset(pre,0,sizeof(pre));
13 }
14 void change(int &x,int y,int l,int r,int p,int w)
15 {
16     x=++num;t[x]=t[y];
17     if(l==r){t[x].s+=w;return;}
18     int m=l+r>>1;
19     if(m<p)change(t[x].r,t[y].r,m+1,r,p,w);
20     else change(t[x].l,t[y].l,l,m,p,w);
21     t[x].s=t[t[x].l].s+t[t[x].r].s;
22 }
23 int query(int x,int l,int r,int L,int R)
24 {
25     if(l==L&&r==R)return t[x].s;
26     int m=l+r>>1;
27     if(L>m)return query(t[x].r,m+1,r,L,R);
28     else if(m>=R)return query(t[x].l,l,m,L,R);
29     else return query(t[x].l,l,m,L,m)+query(t[x].r,m+1,r,m+1,R);
30 }
31 int find(int x,int l,int r,int p)
32 {
33     if(l==r)return l;
34     int m=l+r>>1;
35     if(t[t[x].l].s>=p)return find(t[x].l,l,m,p);
36     return find(t[x].r,m+1,r,p-t[t[x].l].s);
37 }
38 int main()
39 {
40     scanf("%d",&T);int n,m,cnt;
41     for(int ii=1;ii<=T;++ii)
42     {
43         scanf("%d%d",&n,&m);
44         init();
45         for(int i=1;i<=n;++i)scanf("%d",&a[i]);
46         for(int i=n;i;--i)
47         {
48             change(rt[i],rt[i+1],1,n,i,1);
49             if(pre[a[i]])change(rt[i],rt[i],1,n,pre[a[i]],-1);
50             pre[a[i]]=i;
51         }ans[0]=0;
52         for(int i=1;i<=m;++i)
53         {
54             int x,y;
55             scanf("%d%d",&x,&y);
56             x=(x+ans[i-1])%n+1;
57             y=(y+ans[i-1])%n+1;
58             if(x>y)swap(x,y);
59             int k=query(rt[x],1,n,x,y);
60             ans[i]=find(rt[x],1,n,(k+1)/2);
61         }
62         printf("Case #%d:",ii);
63         for(int i=1;i<=m;++i)printf(" %d",ans[i]);
64         puts("");
65     }
66     return 0;
67 }

 

posted @ 2018-02-28 21:40  大奕哥&VANE  阅读(144)  评论(0编辑  收藏  举报