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