• 一道题


    n<=100000个<=100000的正数,其中有一些0表示这个位置的数字可以是L~R中的一个,L,R是给定常数且1<=L<=R<=100000,问最长上升子序列。

    先暴力啊!$f(i,j)$表示前i个数中以j结尾的答案。$f(i,j)=f(i-1,j)$,$f(i,a_i)=max(f(i-1,j)+1),j<a_i$为$a_i$>0的转移方式,而$f(i,j)=max(f(i-1,k)+1),L<=j<=R,k<=j$为$a_i=0$的转移方式。

    不如$f(i,j)$表示前i个数中以$<=j$的结尾的答案,一来是这样表示是一个单调序列,二来转移简洁了些:$f(i,j)=f(i-1,j)$,$f(i,a_i~R)>?=f(i-1,a_i-1),j<a_i$,$f(i,j)=f(i-1,j-1)+1,L<=j<=R$,诸如此类,细节略。

    这些操作,在从i-1变成i时可以用一个平衡树维护。需要区间加,区间赋值,单点查询。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<algorithm>
      4 #include<stdlib.h>
      5 #include<math.h>
      6 //#include<time.h>
      7 //#include<iostream>
      8 using namespace std;
      9 
     10 int n,L,R,m=100001;
     11 #define maxn 100011
     12 int a[maxn];
     13 
     14 inline int max(int x,int y) {return x>y?x:y;}
     15 inline int min(int x,int y) {return x<y?x:y;}
     16 struct Splay
     17 {
     18     struct Node
     19     {
     20         int v,size,Max,Min;
     21         int add,be;
     22         int fa,son[2];
     23     }a[maxn<<1];
     24     int size,root,live,die;
     25     Splay() {size=root=0;}
     26     inline void besingle(int x,int v)
     27     {
     28         if (!x) return;
     29         a[x].v=v; a[x].Max=a[x].Min=v;
     30         a[x].add=0;
     31         a[x].be=v;
     32     }
     33     inline void addsingle(int x,int v)
     34     {
     35         if (!x) return;
     36         a[x].v+=v; a[x].Max+=v; a[x].Min+=v;
     37         if (a[x].be) a[x].be+=v;
     38         else a[x].add+=v;
     39     }
     40     inline void down(int x)
     41     {
     42         const int &p=a[x].son[0],&q=a[x].son[1];
     43         if (a[x].add) addsingle(p,a[x].add),addsingle(q,a[x].add),a[x].add=0;
     44         if (a[x].be) besingle(p,a[x].be),besingle(q,a[x].be),a[x].be=0;
     45     }
     46     inline void up(int x)
     47     {
     48         if (!x || x==live || x==die) return;
     49         const int &p=a[x].son[0],&q=a[x].son[1];
     50         a[x].size=a[p].size+a[q].size+1;
     51         a[x].Max=max(a[p].Max,max(a[q].Max,a[x].v));
     52         a[x].Min=min(a[p].Min,min(a[q].Min,a[x].v));
     53     }
     54     int sta[maxn<<1],top;
     55     inline void download(int x)
     56     {
     57         top=0; for (int i=x;i;i=a[i].fa) sta[++top]=i;
     58         while (top) down(sta[top--]);
     59     }
     60     inline void rotate(int x)
     61     {
     62         const int y=a[x].fa,z=a[y].fa;
     63         bool w=(x==a[y].son[0]);
     64         a[x].fa=z;
     65         if (z) a[z].son[y==a[z].son[1]]=x;
     66         a[y].son[w^1]=a[x].son[w];
     67         if (a[x].son[w]) a[a[x].son[w]].fa=y;
     68         a[x].son[w]=y;
     69         a[y].fa=x;
     70         up(y); up(z);
     71     }
     72     inline void splay(int x,int top)
     73     {
     74         download(x);
     75         while (a[x].fa!=top)
     76         {
     77             const int y=a[x].fa,z=a[y].fa;
     78             if (z!=top)
     79             {
     80                 if ((x==a[y].son[0])^(y==a[z].son[0])) rotate(x);
     81                 else rotate(y);
     82             }
     83             rotate(x);
     84         }
     85         up(x);
     86         if (!top) root=x;
     87     }
     88     inline void build(int &x,int L,int R)
     89     {
     90         if (L>R) {x=0;return;}
     91         x=++size;
     92         a[x].v=a[x].add=a[x].be=0;
     93         if (L==R)
     94         {
     95             a[x].son[0]=a[x].son[1]=0; a[x].size=1; a[x].Max=a[x].Min=0;
     96             if (L==0) live=x; if (L==m+1) die=x; return;
     97         }
     98         const int mid=(L+R)>>1;
     99         if (mid==0) live=x; if (mid==m+1) die=x;
    100         build(a[x].son[0],L,mid-1);
    101         if (a[x].son[0]) a[a[x].son[0]].fa=x;
    102         build(a[x].son[1],mid+1,R);
    103         if (a[x].son[1]) a[a[x].son[1]].fa=x;
    104         up(x);
    105     }
    106     inline void build()
    107     {
    108         a[root].fa=0; build(root,0,m+1); 
    109         a[live].Max=a[die].Max=-0x3f3f3f3f;
    110         a[live].Min=a[die].Min=0x3f3f3f3f;
    111     }
    112     int find(int v)
    113     {
    114         int x=root,ans=0;
    115         while (x)
    116         {
    117             if (a[a[x].son[0]].size<v) ans=x,v-=a[x].size-a[a[x].son[1]].size,x=a[x].son[1];
    118             else x=a[x].son[0];
    119         }
    120         if (ans) splay(ans,0);
    121         return ans;
    122     }
    123     int getv(int id) {return a[find(id)].v;}
    124     inline void join(int x,int y)
    125     {
    126         a[x].fa=a[y].fa=0;
    127         if (x*y==0) {root=x+y; return;}
    128         int z=x;
    129         while (a[z].son[1]) z=a[z].son[1];
    130         splay(z,0);
    131         a[z].son[1]=y; a[y].fa=z; up(z);
    132     }
    133     inline void Delete(int id)
    134     {
    135         int x=find(id);
    136         join(a[x].son[0],a[x].son[1]);
    137     }
    138     inline void copy(int id)
    139     {
    140         int x=find(id),y=a[x].son[1];
    141         while (a[y].son[0]) y=a[y].son[0];
    142         splay(y,x);
    143         int z=++size;
    144         a[z].son[0]=a[z].son[1]=0; a[z].v=a[x].Max=a[x].Min=a[x].v; a[z].size=1; a[z].add=a[z].be=0;
    145         a[z].fa=y; a[y].son[0]=z; up(y); up(x);
    146     }
    147     inline int add(int L,int R,int v)
    148     {
    149         L--; R++;
    150         int y=find(R),x=find(L);
    151         splay(y,x); int z=a[y].son[0];
    152         addsingle(z,v);
    153         up(y); up(x);
    154         return a[z].Max;
    155     }
    156     inline void modmax(int L,int R,int v)
    157     {
    158         L--; R++;
    159         int y=find(R),x=find(L);
    160         splay(y,x); int z=a[y].son[0];
    161         while (1)
    162         {
    163             down(z);
    164             if (a[z].Min>=v) break;
    165             if (a[z].Max<=v) {besingle(z,v); break;}
    166             a[z].v=max(a[z].v,v);
    167             if (!a[z].son[0] && !a[z].son[1]) break;
    168             if (!a[z].son[0] || !a[z].son[1]) z=a[z].son[0]+a[z].son[1];
    169             else if (a[a[z].son[0]].Max<=v) besingle(a[z].son[0],v),z=a[z].son[1];
    170             else z=a[z].son[0];
    171         }
    172         while (z) {up(z); z=a[z].fa;}
    173     }
    174     int ans;
    175     inline void dfs(int x)
    176     {
    177         ans=max(ans,a[x].v);
    178         down(x);
    179         if (a[x].son[0]) dfs(a[x].son[0]);
    180         if (a[x].son[1]) dfs(a[x].son[1]);
    181     }
    182     int getans()
    183     {
    184         ans=0;
    185         dfs(root);
    186         return ans;
    187     }
    188 }t;
    189 
    190 int qread()
    191 {
    192     char c;int s=0; while (!((c=getchar())>='0' && c<='9'));
    193     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
    194 }
    195 int main()
    196 {
    197 //    freopen("orzzsn.in","r",stdin);
    198 //    freopen("orzzsn.out","w",stdout);
    199     scanf("%d%d%d",&n,&L,&R);
    200     for (int i=1;i<=n;i++) a[i]=qread();
    201     
    202     t.build();
    203     for (int i=1;i<=n;i++)
    204     {
    205         if (a[i]) t.modmax(a[i]+1,m+1,t.getv(a[i])+1);
    206         else
    207         {
    208             t.Delete(R+1);
    209             t.copy(L);
    210             t.modmax(R+2,m+1,t.add(L+1,R+1,1));
    211         }
    212     }
    213     printf("%d
    ",t.getans());
    214     return 0;
    215 }
    View Code

    然而不用这样。 维护这个序列的差分即可。假如当前要更新$[L,R]$,那就在L这里插入一个+1标记,在R右边删掉最左的一个差分标记即可,就包含了区间加和区间取Max的操作。

  • 相关阅读:
    ring0 ShadowSSDTHook
    ring0 恢复SSDTHook
    Go的CSP并发模型
    [转]An overview of Openvswitch implementation
    堆排序
    集群 分布式
    云介绍
    云分层
    happens-before
    Java异常
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8081270.html
Copyright © 2020-2023  润新知