zoukankan      html  css  js  c++  java
  • [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('
    ');
    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
  • 相关阅读:
    C语言-define 与do{}while(0)
    Altium Designer 15 --- PCB 3D View
    算法工程师
    VS2015安装失败
    C++11新标准学习
    Sophus VS2010编译不支持?C++11语法的缘故。那有没有不带C++11特性的Sophus版本呢?
    如何学习C++? C++ Primer第三版中文版
    C++智能指针shared_ptr
    C++创建自己的库文件(dll文件创建和编译)
    ARKit对安卓的提示 ARKit与Google Tango
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5140663.html
Copyright © 2011-2022 走看看