• 洛谷 P4137 Rmq Problem / mex


    https://www.luogu.org/problemnew/show/P4137

    只会log^2的带修主席树。。

    看了题解,发现有高妙的一个log做法:权值线段树上,设数i对应的值ma[i]为数i首次出现的位置(没有出现就是n+1)

    如果把询问按左端点排序,这样就转化为:修改:...;询问:询问[1,r]的答案

    修改问题不大

    询问[1,r]就转化为查询当前权值线段树上最小的数i,其对应的ma[i]>r;维护一下区间最大值,然后线段树上二分即可

    可持久化一下线段树,还可以支持在线

    。。。好吧可持久化的话有点卡空间,发现mex一定<=n,那么线段树可以少开一点

    哎,还是思路不够灵活啊...

    跑的极其慢?

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 #include<map>
     6 using namespace std;
     7 #define fi first
     8 #define se second
     9 #define mp make_pair
    10 #define pb push_back
    11 typedef long long ll;
    12 typedef unsigned long long ull;
    13 typedef pair<int,int> pii;
    14 namespace S
    15 {
    16 const int N=8000000;
    17 int maxn[N],lc[N],rc[N];
    18 int mem;
    19 int getnode(int f)
    20 {
    21     int t=++mem;
    22     maxn[t]=maxn[f];lc[t]=lc[f];rc[t]=rc[f];
    23     return t;
    24 }
    25 void setx(int L,int x,int l,int r,int &num)
    26 {
    27     num=getnode(num);
    28     if(l==r)    {maxn[num]=x;return;}
    29     int mid=l+((r-l)>>1);
    30     if(L<=mid)    setx(L,x,l,mid,lc[num]);
    31     else    setx(L,x,mid+1,r,rc[num]);
    32     maxn[num]=max(maxn[lc[num]],maxn[rc[num]]);
    33 }
    34 int getx(int R,int l,int r,int num)
    35 {
    36     if(l==r)    return l;
    37     int mid=l+((r-l)>>1);
    38     if(maxn[lc[num]]>R)    return getx(R,l,mid,lc[num]);
    39     else    return getx(R,mid+1,r,rc[num]);
    40 }
    41 }
    42 int rt[200100];
    43 int a[200100],nxt[200100];
    44 int n,m;
    45 map<int,int> ma;
    46 const int ld=0,rd=200000;
    47 int main()
    48 {
    49     int i,l,r;
    50     S::maxn[0]=0x3f3f3f3f;
    51     scanf("%d%d",&n,&m);
    52     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    53     for(i=n;i>=1;i--)
    54     {
    55         nxt[i]=ma.count(a[i])?ma[a[i]]:n+1;
    56         ma[a[i]]=i;
    57         if(a[i]<=n)    S::setx(a[i],i,ld,rd,rt[1]);
    58         //printf("1a %d %d
    ",a[i],i);
    59     }
    60     for(i=2;i<=n;i++)
    61     {
    62         rt[i]=rt[i-1];
    63         if(a[i-1]<=n)    S::setx(a[i-1],nxt[i-1],ld,rd,rt[i]);
    64         //printf("%da %d %d
    ",i,a[i-1],nxt[i-1]);
    65     }
    66     while(m--)
    67     {
    68         scanf("%d%d",&l,&r);
    69         printf("%d
    ",S::getx(r,ld,rd,rt[l]));
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    [Go] 写文件和判断文件是否存在
    [日常] 解决github速度特别慢
    [Go] imap收信非并发
    [Linux] 使用secureCRT实现SSH隧道服务器端口转发到本机内网穿透
    [Linux] 解决nginx: [emerg] directive "rewrite" is not terminated by ";"
    [MySQL] 解决Error 1698: Access denied for user 'root'@'localhost'
    [Go] gocron源码阅读-判断是否使用root用户执行
    [日常] 前端资源测试机上忽略版本号的的nginx配置
    [Go] 使用go mod安装beego
    [Go] tcp服务下的数据传递
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9575566.html
Copyright © 2020-2023  润新知