题意:给你一串长度为n的序列 你的任务是删除一个连续的子序列 使得剩下的序列中有一个长度最大的连续递增子序列 例如 将 5 3 4 9 2 8 6 7 1 中的9 2 8 删除 得到5 3 4 6 7 1 中包含一个长度为四的连续子序列
紫书的分析十分好 从n3 到n2 到nlongn 非常精妙 此题细节很多 非常值得学习!!! 注意优先队列的写法。
#include<bits/stdc++.h> using namespace std; #define N 200000+5 int a[N]; int n; int g[N];// g[i] is the length of longest increasing continuous subsequence ending at i int f[N]; struct node { int a,g; node(int a,int g):a(a),g(g){} bool operator< (const node &h)const{ return a<h.a; } }; set<node> s; int main() { int cas;cin>>cas; while(cas--) { cin>>n; for(int i=0;i<n;i++)scanf("%d",&a[i]); g[0]=1; for(int i=1;i<n;i++) if(a[i]>a[i-1])g[i]=g[i-1]+1; else g[i]=1; f[n-1]=1; for(int i=n-2;i>=0;i--) if(a[i]<a[i+1])f[i]=f[i+1]+1; else f[i]=1; s.clear(); s.insert(node(a[0],g[0])); int ans=1; for(int i=1;i<n;i++) { node c(a[i],g[i]); set<node>::iterator it=s.lower_bound(c);// first one that is >= c bool keep=true; if(it!=s.begin()) { node last=*(--it);//points to the largest one that is < c int len=f[i]+last.g; ans=max(ans,len); if(c.g<=last.g)keep=false; } if(keep) { s.insert(c); it=s.find(c);// this is a bit cumbersome and slow but it's clear it++; while(it!=s.end()&&it->a >c.a&&it->g<=c.g)s.erase(it++); } } printf("%d ",ans); } return 0; }