码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3489 A simple rmq problem 可持久化树套树

时间:2015-05-27 13:40:16      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:

  先预处理出两个个数组pre,next。pre[i]表示上一个与i位置数字相同的位置,若不存在则设为0;next[i]表示下一个与i位置数字相同的位置,若不存在则设为n+1。那么一个满足在区间[L,R]中只出现一次的数字,其pre[i]<L,next[i]>R。

  这样我们可以先将pre进行排序,然后将pre可持久化,外层线段树套的是当前数字的位置i,内层线段树套的是next[i]。外层线段树的节点总数是nlogn,内层线段树节点总数是nlogn^2。时间复杂度O(nlogn^2)。

  代码

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define N 40000000
  5 #define M 100010
  6 #define Q 2000000
  7 using namespace std;
  8 int n,m,i,a[M],tmp[M],tt,stt,ls[Q],rs[Q],root[M],L,R,e[M];
  9 int subroot[Q],u,v,ans;
 10 struct ff
 11 {
 12     int next,pre,idx;
 13 }f[M];
 14 struct g
 15 {
 16     int ls,rs,s;
 17 }sub[N];
 18 inline void ll(int x,int y)
 19 {
 20     ls[x]=ls[y];
 21 }
 22 inline void rr(int x,int y)
 23 {
 24     rs[x]=rs[y];
 25 }
 26 inline void sl(int x,int y)
 27 {
 28     sub[x].ls=sub[y].ls;
 29 }
 30 inline void sr(int x,int y)
 31 {
 32     sub[x].rs=sub[y].rs;
 33 }
 34 bool cmp(ff a,ff b)
 35 {
 36     return a.pre<b.pre;
 37 }
 38 void subinsert(int &x,int y,int l,int r,int a,int b)
 39 {
 40     int m;
 41     stt++;x=stt;
 42     sub[x].s=max(sub[y].s,b);
 43     if (r-l==1) return;
 44         m=(l+r)>>1;
 45         sl(x,y);
 46         sr(x,y);
 47         if (a-1<m) subinsert(sub[x].ls,sub[y].ls,l,m,a,b);
 48         if (m<a)  subinsert(sub[x].rs,sub[y].rs,m,r,a,b);
 49 }
 50 void insert(int &x,int y,int l,int r,int a,int b,int c)
 51 {
 52     int m;
 53     tt++;x=tt;
 54     subinsert(subroot[x],subroot[y],0,n+1,b,c);
 55     if (r-l==1) return;
 56     m=(l+r)>>1;
 57     ll(x,y);rr(x,y);
 58     if (a-1<m) 
 59     insert(ls[x],ls[y],l,m,a,b,c);
 60     if (m<a)
 61     insert(rs[x],rs[y],m,r,a,b,c);
 62 }
 63 int subquery(int x,int l,int r,int a,int b)
 64 {
 65     int m,ans=0;
 66     if (x==0) return 0;
 67     if ((a<=l)&&(r<=b))
 68         return sub[x].s;
 69     m=(l+r)>>1;
 70     if (a<m) ans=max(ans,subquery(sub[x].ls,l,m,a,b));
 71     if (m<b) ans=max(ans,subquery(sub[x].rs,m,r,a,b));
 72     return ans;
 73 }
 74 int query(int x,int l,int r,int a,int b)
 75 {
 76     int m,ans=0;
 77     if (x==0) return 0;
 78     if ((a<=l)&&(r<=b))    
 79         return subquery(subroot[x],0,n+1,b,n+1);
 80     m=(l+r)>>1;
 81     if (a<m) ans=max(ans,query(ls[x],l,m,a,b));
 82     if (m<b) ans=max(ans,query(rs[x],m,r,a,b));
 83     return ans;
 84 }
 85 int main()
 86 {
 87     scanf("%d%d",&n,&m);
 88     for (i=1;i<=n;i++)
 89         scanf("%d",&a[i]);
 90     for (i=1;i<=n;i++)
 91     {
 92         f[i].pre=tmp[a[i]];
 93         tmp[a[i]]=i;
 94     }
 95     for (i=1;i<=n;i++)
 96     tmp[i]=n+1;
 97     for (i=n;i>=1;i--)
 98     {
 99         f[i].next=tmp[a[i]];
100         tmp[a[i]]=i;
101         f[i].idx=i;
102     }
103     sort(f+1,f+1+n,cmp);
104     for (i=1;i<=n;i++)
105     {
106         insert(root[i],root[i-1],0,n,f[i].idx,f[i].next,a[f[i].idx]);
107     }
108     for (i=1;i<=n;i++)
109      e[f[i].pre]=i;
110     for (i=1;i<=n;i++)
111      if (e[i]==0)
112      e[i]=e[i-1];
113     for (i=1;i<=m;i++)
114     {
115         scanf("%d%d",&u,&v);
116         L=(u+ans)%n+1;
117         R=(v+ans)%n+1;
118         if (L>R) swap(L,R);
119         ans=query(root[e[L-1]],0,n,L-1,R);
120         printf("%d\n",ans);
121     }
122 }

 

bzoj3489 A simple rmq problem 可持久化树套树

标签:

原文地址:http://www.cnblogs.com/fzmh/p/4533120.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!