题目链接:http://codeforces.com/contest/650/problem/D
大意是给一个数组,若干询问,每一次把一个数字改为另一个数字,问当前数组最长上升子序列,询问之间是独立的。
注意到:假设初始数组的LIS长度为len。如果某一个位置的数字属于所有LIS,那么即便这个位置的数字被更改,答案至少是len-1,也有可能会因为变化维持len不变(未必是因为变化介于原来LIS前一个数字和后一个数字之间)。如果某一个位置的数字不是属于所有的LIS(属于某一种或者不属于任何LIS),那么答案至少是len,但也有可能因为变化新答案为len+1。至此,处理出所有位置的数字是否属于所有LIS的情况后,所有询问有了保底的答案。对于这两种情况,可能会产生不保底的情况,则需要对每一个询问查询,左边小于新数字的最大dp值,与右边大于新数字的最大dp值,两者相加再加上1与保底答案取最大值。具体操作,可以按照询问的位置对询问排序,离线处理。
具体写法有两种,一种是树状数组对原有数组数字与询问新数字全部离散化处理,以及基于LIS O(nlog(n))二分解法的写法。判断一个数字是否属于某一个LIS,条件是f[i]+g[i]==len-1? 其中f[i]和g[i]分别是以a[i]为结尾从1到i的LIS长度以及以a[i]为开端从i到n的LIS长度。判断一个数字是否属于所有LIS,则扫描所有属于某一种LIS的数字,统计它们的f值或者g值出现次数,如果某一个f值只出现了1次,则说明拥有这个f值的数字被所有LIS经过。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <math.h> 8 #include <stdlib.h> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 16 const int N=1e6+12345; 17 int a[N],b[N]; 18 struct Query { 19 int p,v; 20 int id; 21 int ans; 22 int l,r; 23 bool operator < (const Query &o) const { 24 return p<o.p; 25 } 26 }query[N]; 27 28 int t[N]; 29 inline int lowbit(int x) { 30 return x&(-x); 31 } 32 void upd(int x,int v) { 33 for (;x<N;x+=lowbit(x)) 34 t[x]=max(t[x],v); 35 } 36 int ask(int x) { 37 int ret=0; 38 for (;x;x-=lowbit(x)) 39 ret=max(ret,t[x]); 40 return ret; 41 } 42 int lis(int n,int *f){ 43 memset(t,0,sizeof t); 44 int ret=0; 45 for (int i=0;i<n;i++) { 46 int d=ask(a[i]-1); 47 upd(a[i],d+1); 48 f[i]=d+1; 49 ret=max(ret,d+1); 50 } 51 return ret; 52 } 53 bool flag[N];int cnt[N]; 54 int ret[N]; 55 int f[N],g[N]; 56 int main(){ 57 int n,m; 58 scanf("%d %d",&n,&m); 59 for (int i=0;i<n;i++) { 60 scanf("%d",a+i); 61 b[i]=a[i]; 62 } 63 int tot=n; 64 for (int i=0;i<m;i++) { 65 int x,y; 66 scanf("%d %d",&x,&y); 67 query[i].p=x-1; 68 query[i].v=y; 69 query[i].id=i; 70 b[tot++]=y; 71 } 72 sort(b,b+tot); 73 int k=unique(b,b+tot)-b; 74 for (int i=0;i<n;i++) { 75 a[i]=lower_bound(b,b+k,a[i])-b+1; 76 } 77 for (int i=0;i<m;i++) { 78 query[i].v=lower_bound(b,b+k,query[i].v)-b+1; 79 } 80 int len=lis(n,f); 81 for (int i=0;i<n;i++) { 82 a[i]=N-a[i]; 83 } 84 reverse(a,a+n); 85 lis(n,g); 86 reverse(g,g+n); 87 88 reverse(a,a+n); 89 for (int i=0;i<n;i++) { 90 a[i]=N-a[i]; 91 } 92 93 memset(cnt,0,sizeof cnt); 94 for (int i=0;i<n;i++) { 95 if (f[i]+g[i]-1==len) { 96 cnt[f[i]]++; 97 } 98 } 99 for (int i=0;i<n;i++) { 100 if (f[i]+g[i]-1==len&&cnt[f[i]]==1) { 101 flag[i]=true; 102 } 103 } 104 105 sort(query,query+m); 106 for (int i=0;i<m;i++) { 107 int p=query[i].p; 108 if (flag[p]) 109 query[i].ans=len-1; 110 else 111 query[i].ans=len; 112 } 113 int st=0; 114 memset(t,0,sizeof t); 115 for (int i=0;i<m;i++) { 116 int p=query[i].p; 117 for (;st<p;st++) { 118 int d=ask(a[st]-1); 119 upd(a[st],d+1); 120 } 121 int d=ask(query[i].v-1); 122 query[i].l=d; 123 } 124 memset(t,0,sizeof t); 125 for (int i=0;i<n;i++) { 126 a[i]=N-a[i]; 127 } 128 st=n-1; 129 for (int i=m-1;i>=0;i--) { 130 int p=query[i].p; 131 query[i].v=N-query[i].v; 132 for (;st>p;st--) { 133 int d=ask(a[st]-1); 134 upd(a[st],d+1); 135 } 136 int d=ask(query[i].v-1); 137 query[i].r=d; 138 query[i].ans=max(query[i].ans,query[i].l+query[i].r+1); 139 ret[query[i].id]=query[i].ans; 140 } 141 for (int i=0;i<m;i++) { 142 printf("%d\n",ret[i]); 143 } 144 return 0; 145 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <math.h> 8 #include <stdlib.h> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 16 const int N=1e6+12345; 17 const int INF=0x3f3f3f3f; 18 int a[N]; 19 struct Query { 20 int p,v; 21 int id; 22 int ans; 23 int l,r; 24 bool operator < (const Query &o) const { 25 return p<o.p; 26 } 27 }query[N]; 28 int dp[N]; 29 int f[N],g[N]; 30 int cnt[N]; 31 int lis(int n,int *f){ 32 fill(dp,dp+n,INF); 33 for (int i=0;i<n;i++) { 34 int pos=lower_bound(dp,dp+n,a[i])-dp; 35 dp[pos]=a[i]; 36 f[i]=pos+1; 37 } 38 return lower_bound(dp,dp+n,INF)-dp; 39 } 40 bool flag[N]; 41 int ret[N]; 42 int main(){ 43 int n,m; 44 scanf("%d %d",&n,&m); 45 for (int i=0;i<n;i++) { 46 scanf("%d",a+i); 47 } 48 for (int i=0;i<m;i++) { 49 int x,y; 50 scanf("%d %d",&x,&y); 51 query[i].p=x-1; 52 query[i].v=y; 53 query[i].id=i; 54 } 55 56 int len=lis(n,f); 57 for (int i=0;i<n;i++) { 58 a[i]=-a[i]; 59 } 60 reverse(a,a+n); 61 62 lis(n,g); 63 reverse(g,g+n); 64 65 66 for (int i=0;i<n;i++) { 67 a[i]=-a[i]; 68 } 69 reverse(a,a+n); 70 71 memset(cnt,0,sizeof cnt); 72 for (int i=0;i<n;i++) { 73 if (f[i]+g[i]-1==len) { 74 cnt[f[i]]++; 75 } 76 } 77 for (int i=0;i<n;i++) { 78 if (f[i]+g[i]-1==len&&cnt[f[i]]==1) { 79 flag[i]=true; 80 } 81 } 82 83 sort(query,query+m); 84 for (int i=0;i<m;i++) { 85 int p=query[i].p; 86 if (flag[p]) 87 query[i].ans=len-1; 88 else 89 query[i].ans=len; 90 } 91 92 int st=0; 93 fill(dp,dp+n,INF); 94 for (int i=0;i<m;i++) { 95 int p=query[i].p; 96 for (;st<p;st++) { 97 int pos=lower_bound(dp,dp+n,a[st])-dp; 98 dp[pos]=a[st]; 99 } 100 int pos=lower_bound(dp,dp+n,query[i].v)-dp; 101 query[i].l=pos; 102 } 103 104 105 for (int i=0;i<n;i++) { 106 a[i]=-a[i]; 107 } 108 st=n-1; 109 fill(dp,dp+n,INF); 110 for (int i=m-1;i>=0;i--) { 111 int p=query[i].p; 112 for (;st>p;st--) { 113 int pos=lower_bound(dp,dp+n,a[st])-dp; 114 dp[pos]=a[st]; 115 } 116 int pos=lower_bound(dp,dp+n,-query[i].v)-dp; 117 query[i].r=pos; 118 query[i].ans=max(query[i].ans,query[i].l+query[i].r+1); 119 ret[query[i].id]=query[i].ans; 120 } 121 for (int i=0;i<m;i++) { 122 printf("%d\n",ret[i]); 123 } 124 return 0; 125 }