CF650D Zip-line[单点修改并查询的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 }