[dp][lis] Jzoj P5920 风筝
题解
- 首先,我们先求出两个东西lis1和lis2,分别为以i结尾和以i为开始的lis
- 然后再来考虑一下修改后的情况
- ①a在lis中 ②a不在lis中
- 如果a在lis中,如果当前修改的数的lis1+lis2-1大于lis那么直接输出
- 还有一种情况也就是修改后lis就变短了,但是呢,lis可能会有多个,也就是说如果当前这个位修改后有没有其它lis来替换
- 举个例子:1245,这个显然有两个lis,①124 ②125
- 如果修改4为1后,第一个lis显然会变短,但是对第二个没有影响
- 那么就可以这样做,将lis的每一个位置不同的数都++,也就是d[lis1[i]]++,因为lis1是以i结尾的lis的长度,那么其实就是在lis中的位置
- 最后一种情况就是a不在lis中,那就简单了,直接输出lis的长度
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #define N 500010 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 struct edge{int x,d,v,a,b;}Q[N]; 9 int n,m,len,l,h[N],lis1[N],lis2[N],ans[N],k[N],f[N]; 10 bool cmp(edge a,edge b){ return a.x<b.x; } 11 int main() 12 { 13 freopen("kite.in","r",stdin),freopen("kite.out","w",stdout); 14 scanf("%d%d",&n,&m); 15 for (int i=1;i<=n;i++) scanf("%d",&h[i]); 16 for (int i=1,x,y;i<=m;i++) scanf("%d%d",&Q[i].x,&Q[i].v),Q[i].d=i; 17 sort(Q+1,Q+m+1,cmp); 18 l=1; 19 for (int i=1;i<=n;i++) f[i]=inf; 20 for (int i=1;i<=n;i++) 21 { 22 while (l<=m&&Q[l].x==i) 23 { 24 int p=lower_bound(f+1,f+n+1,Q[l].v)-f; 25 Q[l].a=p,l++; 26 } 27 int p=lower_bound(f+1,f+n+1,h[i])-f; 28 lis1[i]=p,f[p]=h[i],len=max(p,len); 29 } 30 l=m; 31 for (int i=1;i<=n;i++) f[i]=inf; 32 for (int i=n;i>=1;i--) 33 { 34 while (l>0&&Q[l].x==i) 35 { 36 int p=lower_bound(f+1,f+n+1,-Q[l].v)-f; 37 Q[l].b=p,l--; 38 } 39 int p=lower_bound(f+1,f+n+1,-h[i])-f; 40 lis2[i]=p,f[p]=-h[i]; 41 } 42 for (int i=1;i<=n;i++) if (lis1[i]+lis2[i]-1==len) k[lis1[i]]++; 43 for (int i=1;i<=m;i++) 44 if (Q[i].a+Q[i].b>len) ans[Q[i].d]=Q[i].a+Q[i].b-1; 45 else if (lis1[Q[i].x]+lis2[Q[i].x]>len&&k[lis1[Q[i].x]]==1) ans[Q[i].d]=len-1; 46 else ans[Q[i].d]=len; 47 for (int i=1;i<=m;i++) printf("%d\n",ans[i]); 48 }