专栏文章
题解:P8108 [Cnoi2021] 绀珠传说
P8108题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioxj94r
- 此快照首次捕获于
- 2025/12/03 02:46 3 个月前
- 此快照最后确认于
- 2025/12/03 02:46 3 个月前
考虑将连续相同的段删除等价于什么,即对所有相邻的两列选择一个公共子序列,对应位置合并一起删除。答案即为 减去所有相邻两列 LCS 长度之和。
注意到数据是随机生成的,即同一列中每种颜色的出现次数都是 的,直接枚举匹配的位置树状数组维护转移即可。
时间复杂度 。
参考代码:
CPP#include<bits/stdc++.h>
#define ll long long
#define mxn 1003
#define pb push_back
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rept(i,a,b) for(int i=(a);i<(b);++i)
#define drep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
int n,ans,f[mxn],a[mxn][mxn];
vector<int>s[mxn];
inline void upd(int x,int y){
for(;x<=n;x+=x&-x)f[x]=max(f[x],y);
}
inline int ask(int x){
int s=0;
for(;x;x-=x&-x)s=max(s,f[x]);
return s;
}
signed main(){
scanf("%d",&n),ans=n*n;
rep(i,1,n)rep(j,1,n)scanf("%d",&a[j][i]);
rep(i,2,n){
rep(j,1,n)s[j].clear(),f[j]=0;
drep(j,n,1)s[a[i-1][j]].pb(j);
rep(j,1,n){
for(int x:s[a[i][j]]){
upd(x,ask(x-1)+1);
}
}
ans-=ask(n);
}
cout<<ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...