• CF650D Zipline[单点修改并查询的LIS][主席树]


    题意:

    给定长度为$n$的序列${h_{n}}$,$m$个询问。求对于每次询问$(a_{i},b_{i})$,如果将$a_{i}$改为$b_{i}$,序列的最长严格上升子序列长度。(询问互相独立)


     

    预处理

      $f_{i}$是以$h_{i}$结尾的LIS长度,$g_{i}$是以$h_{i}$开头的LIS长度(代码中为$f[i][0]$和$f[i][1]$)。

      $l$为原序列LIS。

    考虑$a_{i}$是否选择

     若不选$a_{i}$:

      若$a_{i}$是初始序列LIS的必选元素,则$ans=l-1$,否则$ans=l$。

      若$f_{i}+g_{i}==l+1$则为必选元素。

     若选择$a_{i}$:

      则$ans=max \{ f_{j} | h_{j}<b_{i},j<a_{i} \} + max \{ g_{j} | h_{j}>b_{i},j>a_{i} \}+1$

      可以从前往后、从后往前建两棵主席树查询最大值。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 using namespace std;
     6 const int N=500010;
     7 struct tree {
     8     int l,r,mx;
     9 } t[N*40];
    10 int n,m,cnt,tot,f[N][2],rt[N][2],g[N],h[N],l,r,mid,a,b,ans1,ans2,tmp,pos,F,G,key[N];
    11 vector<int> v;
    12 inline int read() {
    13     int re=0; char ch=getchar();
    14     while (ch<'0'||ch>'9') ch=getchar();
    15     while (ch>='0'&&ch<='9') re=re*10+ch-48,ch=getchar();
    16     return re;
    17 }
    18 inline int lb1(int x) {
    19     l=1; r=g[0];
    20     while (l<r) {
    21         mid=(l+r)>>1;
    22         if (g[mid]<x) l=mid+1;
    23         else r=mid;
    24     }
    25     return l;
    26 }
    27 inline int lb2(int x) {
    28     l=1; r=g[0];
    29     while (l<r) {
    30         mid=(l+r)>>1;
    31         if (g[mid]<=x) r=mid;
    32         else l=mid+1;
    33     }
    34     return l;
    35 }
    36 inline int get(int x) {return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
    37 inline int get1(int x) {return lower_bound(v.begin(),v.end(),x)-v.begin();}
    38 inline int get2(int x) {return upper_bound(v.begin(),v.end(),x)-v.begin()+1;}
    39 void update(int &x,int y,int l,int r) {
    40     t[x=++cnt]=t[y]; t[x].mx=max(t[x].mx,F);
    41     if (l==r) return;
    42     int mid=(l+r)>>1;
    43     if (pos<=mid) update(t[x].l,t[y].l,l,mid);
    44     else update(t[x].r,t[y].r,mid+1,r);
    45 }
    46 int query1(int x,int l,int r,int pos) {
    47     if (l==r) return t[x].mx;
    48     int mid=(l+r)>>1;
    49     if (pos<=mid) return query1(t[x].l,l,mid,pos);
    50     else return max(t[t[x].l].mx,query1(t[x].r,mid+1,r,pos));
    51 }
    52 int query2(int x,int l,int r,int pos) {
    53     if (l==r) return t[x].mx;
    54     int mid=(l+r)>>1;
    55     if (pos>mid) return query2(t[x].r,mid+1,r,pos);
    56     else return max(t[t[x].r].mx,query2(t[x].l,l,mid,pos));
    57 }
    58 int main() {
    59     n=read(); m=read();
    60     for (int i=1; i<=n; i++) {
    61         h[i]=read(),v.push_back(h[i]);
    62         if (!g[0]||h[i]>g[g[0]]) g[f[i][0]=++g[0]]=h[i];
    63         else g[f[i][0]=lb1(h[i])]=h[i];
    64     }
    65     G=g[0]; g[0]=0;
    66     for (int i=n; i>=1; i--) {
    67         if (!g[0]||h[i]<g[g[0]]) g[f[i][1]=++g[0]]=h[i];
    68         else g[f[i][1]=lb2(h[i])]=h[i];
    69     }
    70     for (int i=1; i<=n; i++) if (f[i][0]+f[i][1]==G+1) key[f[i][0]]++;
    71     v.push_back(2147483647); v.push_back(-2147483648);
    72     sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
    73     tot=v.size();
    74     for (int i=1; i<=n; i++) h[i]=get(h[i]);
    75     for (int i=1; i<=n; i++) {
    76         pos=h[i]; F=f[i][0];
    77         update(rt[i][0],rt[i-1][0],1,tot);
    78     }
    79     for (int i=n; i; i--) {
    80         pos=h[i]; F=f[i][1];
    81         update(rt[i][1],rt[i+1][1],1,tot);
    82     }
    83     while (m--) {
    84         a=read(); b=read();
    85         ans1=G-(f[a][0]+f[a][1]==G+1&&key[f[a][0]]<=1);
    86         ans2=query1(rt[a-1][0],1,tot,get1(b))+query2(rt[a+1][1],1,tot,get2(b))+1;
    87         printf("%d\n",max(ans1,ans2));
    88     }
    89     return 0;
    90 }

     

  • 相关阅读:
    udev 禁止某些驱动自动加载
    AT91SAM9XEK ramdisk 启动笔记
    MTD 工具使用
    kmp问题
    野指针 空指针 通用指针
    manacher算法实现
    manacher算法
    strcpy和strlen
    冒泡排序
    C++的重载(overload)与重写(override
  • 原文地址:https://www.cnblogs.com/hnooo/p/10015877.html
Copyright © 2020-2023  润新知