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 }

 

posted @ 2018-11-25 15:52  HNOOO  阅读(378)  评论(0编辑  收藏  举报