1 条题解
-
0
自动搬运
来自洛谷,原作者为

q234rty
**搬运于
2025-08-24 21:49:39,当前版本为作者最后更新于2019-02-10 22:41:27,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
安利窝的博客
相信很多人看到这道题的第一反应和窝一样:这不是水题吗,只要记 表示下标以 结尾的最长合法子序列长度,转移树状数组优化一下就行了。
还有一些人可能觉得这道题需要在状态中记录长度 ,于是得到了优秀的 或 做法。
第一反应觉得这道题是水题之后可能会觉得不对劲,DP 需要最优子结构,而这个 DP 看起来并不满足呀。
然而,这个 DP 确实是满足最优子结构的,为什么呢?
(网上的题解大都没写证明,neither_nor 写了证明但窝看不懂,于是窝决定写一下用谷歌翻译看波兰文官方题解(在 P152)的成果)
就是要证下标以 结尾的最长合法子序列,一定可以由某个下标以 结尾的最长合法子序列接上 得到。
不失一般性,设下标以 结尾的最长合法子序列第一个不满足这个条件,再设 为这个子序列的上一个下标。
设 为下标以 结尾的最长合法子序列对应的下标序列,显然 ,设 。
因为 继承的不是 的最优解,所以 ,即 。
讨论:
- ,这时 长度为 ,显然为一个不会更劣的解。
- ,这就是说 ,继续讨论:
- ,那么 长度为 ,不会更劣。
- ,我们有 ,但是 ,也即一定存在一个 满足 ,也即 ,我们取第一个这样的 ,于是 ,又 ,于是 ,于是 长度为 ,更优。
- ,同理得证。
这样就证完啦。
使用两个树状数组分别维护下一个是大于和小于的情况,等于直接用数组维护。
时间复杂度 。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int MAXSIZE=10000020; int bufpos; char buf[MAXSIZE]; #define NEG 0 void init(){ #ifdef LOCAL freopen("3009.txt","r",stdin); #endif buf[fread(buf,1,MAXSIZE,stdin)]='\0'; bufpos=0; } #if NEG int readint(){ bool isneg; int val=0; for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++); bufpos+=(isneg=buf[bufpos]=='-'); for(;isdigit(buf[bufpos]);bufpos++) val=val*10+buf[bufpos]-'0'; return isneg?-val:val; } #else int readint(){ int val=0; for(;!isdigit(buf[bufpos]);bufpos++); for(;isdigit(buf[bufpos]);bufpos++) val=val*10+buf[bufpos]-'0'; return val; } #endif char readchar(){ for(;isspace(buf[bufpos]);bufpos++); return buf[bufpos++]; } int readstr(char* s){ int cur=0; for(;isspace(buf[bufpos]);bufpos++); for(;!isspace(buf[bufpos]);bufpos++) s[cur++]=buf[bufpos]; s[cur]='\0'; return cur; } const int maxn=1000002; inline void tense(pii &x,pii y){ if (x<y) x=y; } struct bit{ int n; pii t[maxn]; void add(int p,pii v){ for(;p<=n;p+=p&-p) tense(t[p],v); } pii query(int p){ pii ans; for(;p;p-=p&-p) tense(ans,t[p]); return ans; } }b1; struct tib{ int n; pii t[maxn]; void add(int p,pii v){ for(;p;p-=p&-p) tense(t[p],v); } pii query(int p){ pii ans; for(;p<=n;p+=p&-p) tense(ans,t[p]); return ans; } }b2; inline pii inc(pii x){ x.first++; return x; } int a[maxn],dp[maxn],lst[maxn],stk[maxn]; pii qwq[maxn]; char s[maxn]; int main(){ init(); int n=readint(),k=readint(); for(int i=1;i<=n;i++) a[i]=readint(); for(int i=1;i<=k;i++) s[i]=readchar(); b1.n=b2.n=maxn-1; int ans=0; for(int i=1;i<=n;i++){ pii lol; tense(lol,inc(b1.query(a[i]-1))); tense(lol,inc(b2.query(a[i]+1))); tense(lol,inc(qwq[a[i]])); dp[i]=lol.first,lst[i]=lol.second; // printf("dp[%d]=%d lst[%d]=%d\n",i,dp[i],i,lst[i]); lol.second=i; char now=s[(dp[i]-1)%k+1]; if (now=='=') tense(qwq[a[i]],lol); else if (now=='<') b1.add(a[i],lol); else b2.add(a[i],lol); // printf("dp[%d]=%d lst[%d]=%d\n",i,dp[i],i,lst[i]); if (dp[i]>dp[ans]) ans=i; } printf("%d\n",dp[ans]); int cur=0; while(ans){ stk[++cur]=ans; ans=lst[ans]; } for(int i=cur;i;i--) printf("%d ",a[stk[i]]); }
- 1
信息
- ID
- 2582
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者