[bzoj3489]A simple rmq problem

  本题既不是rmq也不会simple(对我这种蒟蒻而言)

  一开始只能想到树套树套树TAT然后看了看数据范围果断滚去膜拜题解。

  然后才知道预先排序一下可以弄掉一个log。不过得写可持久化线段树套可持久化线段树。。

  然后愉悦的开码了。。。感人的是竟然不用调。。。更感人的是交上去直接tle了。

  然后从网上找了别人的代码(方法一样)发现同样的数据我要跑6s+。。标称只要2s+。。

  之后各种卡常还是慢了一倍TAT。。。最后自己写个max函数就和标程一样快了TAT这几天怎么总是出些奇怪的状况QAQ。

  本来故事到这里就应该结束了。。等评测的时候连标题都想好了:“一个max函数引发的惨剧”

  然而交上去还是tle了(掀桌。。。然后发现标程也tle了。。。然后想起一开始的时候标程数组范围开小。。在看了下hint。。果然出题人把数据加强了不少。大概结局就是写树套树的都tle了。。。。。。。。。。。。。。。。。老板来一打刀片?

 

 具体做法:用pre[i]和next[i]表示前后最近的与第i个数字相同的数字的位置。在区间[l,r]中只出现一次的数字(假设是第i个位置上的数)一定满足pre[i]<l,且next[i]>r。

  直接强行搞的话要三个log。。或者是kd树什么的(三维)。

  然后根据Po姐的题解可得(TAT),我们先把各个数字按照pre值升序排序,按新的顺序,把另外的两个值(next和位置)插入到线段树套线段树里面(外层是按next值,内层是位置)。

  持久化一下,每次查询的时候就在 pre值<l的最后一个数 插入后的那个版本的树套树里面查询。插入的时候外层新增那条链上的内层线段树,在上一个版本的基础上新增一条链就好了。

  按pre值排序和按next值排序都是一样的道理。。

  时间复杂度O(m log²n),空间复杂度O(n log²n)....

直接贴tle的代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=100233;
 7 struct poi{
 8     int pos,pr,af,num;
 9 }a[maxn];
10 int pr[maxn],af[maxn];
11 int rt_out[maxn],rt[maxn*18],lc[maxn*18],rc[maxn*18],tt;
12 int mx[400*maxn],l[400*maxn],r[400*maxn],tot;
13 int i,j,n,m,L,R,lastans,v,v1;
14 
15 int ra;char rx;
16 inline int read(){
17     rx=getchar(),ra=0;
18     while(rx<'0'||rx>'9')rx=getchar();
19     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
20 }
21 char qaq[7];int len;
22 inline void outx(int x){
23     if(!x){puts("0");return;}
24     while(x)qaq[len++]=x%10,x/=10;
25     while(len)putchar(qaq[--len]+'0');putchar('\n');
26 }
27 inline int max(int x,int y){return x<y?y:x;}
28 
29 
30 inline void ins(int pre,int &x,int L,int R){
31     x=++tot,mx[x]=mx[pre];
32     if(a[i].num>mx[x])mx[x]=a[i].num;
33     if(L==R)return;
34     register int mid=(L+R)>>1;
35     if(v<=mid)r[x]=r[pre],ins(l[pre],l[x],L,mid);
36     else l[x]=l[pre],ins(r[pre],r[x],mid+1,R);
37 }
38 int zs;
39 inline int getmx(int x,int L,int R,int c,int d){
40     if(!x)return 0;
41     if(c<=L&&d>=R)return mx[x];register int mid=(L+R)>>1;
42     if(c>mid)return getmx(r[x],mid+1,R,c,d);else
43     if(d<=mid)return getmx(l[x],L,mid,c,d);else
44     return max(getmx(l[x],L,mid,c,d),getmx(r[x],mid+1,R,c,d));
45     
46 }
47 
48 
49 
50 
51 inline void insert(int pre,int&x,int L,int R){
52     x=++tt,ins(rt[pre],rt[x],1,n);
53     if(L==R)return;
54     register int mid=(L+R)>>1;
55     if(v1<=mid)rc[x]=rc[pre],insert(lc[pre],lc[x],L,mid);
56     else lc[x]=lc[pre],insert(rc[pre],rc[x],mid+1,R);
57 }
58 inline int query(int x,int l,int r,int c,int d){
59     if(!x)return 0;
60     if(c<=l&&d>=r)return getmx(rt[x],1,n,L,R);
61     register int mid=(l+r)>>1;
62     if(c>mid)return query(rc[x],mid+1,r,c,d);
63     else return max(getmx(rt[rc[x]],1,n,L,R),query(lc[x],l,mid,c,d));
64 }
65 
66 
67 
68 
69 bool cmp(poi a,poi b){return a.pr<b.pr;}
70 int main(){
71     n=read(),m=read();
72     for(i=1;i<=n;i++)a[i].pos=i,a[i].pr=pr[a[i].num=read()],pr[a[i].num]=i;
73     for(i=n;i;i--)a[i].af=af[a[i].num]?af[a[i].num]:(n+1),af[a[i].num]=i;
74     sort(a+1,a+1+n,cmp);
75     for(i=1;i<=n;i++)v=a[i].pos,v1=a[i].af,insert(rt_out[i-1],rt_out[i],1,n+1);
76     for(i=1;i<=m;i++){
77         L=read()+lastans,R=read()+lastans;
78         if(L>=n)L%=n;if(R>=n)R%=n;
79         L++,R++;if(L>R)swap(L,R);
80         register int l=1,r=n,mid;
81         for(;l<r;a[mid].pr<L?(l=mid):(r=mid-1)) mid=(l+r+1)>>1;
82         lastans=query(rt_out[l],1,n+1,R+1,n+1);
83         outx(lastans);
84     }
85     return 0;
86 }
View Code

 

posted @ 2016-01-18 22:08  czllgzmzl  阅读(695)  评论(0编辑  收藏  举报