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

little_sheep917
我太菜了 QvQ搬运于
2025-08-24 22:33:10,当前版本为作者最后更新于2021-08-31 21:32:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
图书馆里有 个书架,每个书架可以放 本书。小C是一位优秀的图书管理员,所以他决定整理图书馆中的所有图书,如果可以的话,把所有图书放回它们原来的位置。他打算用下面的方法来整理图书:
1.如果书架上的某本书的左边或右边是空的,就可以把这本书书向左或向右移动。
2.把一本书从书架上拿起来,再放回到另一个空的位置(可以是任意一个书架)。
可是没过多久小 C 就累了。如果他手上已经有了一本书,他就不能再移动其他的书。而且因为把书拿出来又放回去实在太麻烦了,所以小 C 希望尽可能少地将书从书架上拿起来(即步骤2)。请帮小 C 算出,他最少需要将书拿出来多少次。
感觉做法挺奇妙的 .
一行一行地考虑 .
先考虑当前行和最终行出现书本相同的情况 . 此时,又分出来两种 ,有空位和无空位 .
- 有空位,相当于,找到一本书,再放到它原本的位置上 . 那么,要选出 本书,这 本书相对顺序是正确的,其他的书要根据这 本书的位置放入 . 会发现,这是一个 lis 的问题 . 那么,可以 地解决.
- 没有空位,此时分为两种情况 .
- 当前行与目标行相同 . 无需操作 .
- 当前行与目标行不同,如果其他书架上没有空位,则输出 -1 . 否则,将当前行中一本不位于 本书中的书放到其他书架上,再将当前行排序,排完序后直接插入正确的位置,时间复杂度为 .
考虑玩当前行和最终行出现书本相同的情况,下面就是不同的 .
如果最终应该出现在第 行的书出现在了第 行,那么,由 向 连一条有向边 ,得到一个有向图 ;将 中的有向边变成无向,可以得到一个无向图 . 对于 中的每一个连通块,在 中可以加上一些虚构的有向边,是的其变成一个具有欧拉回路的图 .
那么,对于这个欧拉回路,就是一个移动的方案,但是,这个方案的开始,必定是存在一个连通块中的行有一个空位 . 如果其他的行没有空位的话,那么,必定是不可行的,要输出 -1 .否则,如果连通块不存在空位,需要拿出一本书放在另一行中,然后再移动 ,代价加 .
因为从当前书架拿起,放到其他书架的书必定花费代价 ,而且必定会放到正确的相对位置上 . 代价就是原来就同时存在与当前和最终行中的书的和 - 当前和最终行中的书的和的 lis + 在最终行但不在当前行的书的数量 . 再加上启动时可能需要的 代价.
时间复杂度 :
空间复杂度 :
code
#include<bits/stdc++.h> using namespace std; inline int read(){ char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); int res=0; while(ch>='0'&&ch<='9'){ res=res*10+ch-'0'; ch=getchar(); } return res; } inline void print(int res){ if(res==0){ putchar('0'); return; } int a[8],len=0; while(res>0){ a[len++]=res%10; res/=10; } for(int i=len-1;i>=0;i--)putchar(a[i]+'0'); } const int inf=1e9+10; int n,m; int a[1010][1010],b[1010][1010],nu[1010*1010]; int pos[1010*1010]; bool ok[1010],spare=false; int exist[1010*1010]; int ans=0; int bit[1010]; inline void upd(int i,int val){ while(i<=m){ bit[i]=max(bit[i],val); i+=i&-i; } } inline int qry(int i){ int res=0; while(i){ res=max(res,bit[i]); i-=i&-i; } return res; } vector<int>v,g[1010]; bool vis[1010]; void dfs(int x){ vis[x]=true;v.push_back(x); for(int i=0;i<(int)g[x].size();i++){ int to=g[x][i]; if(!vis[to])dfs(to); } } int solve(int id){ // cout<<endl; // for(int i=0;i<m;i++)cout<<a[id][i]<<" ";cout<<endl; // for(int i=0;i<m;i++)cout<<b[id][i]<<" ";cout<<endl; int cnt=0; for(int i=0;i<m;i++)if(a[id][i]>0)nu[a[id][i]]=cnt++; for(int i=0;i<=m;i++)bit[i]=0; for(int i=0;i<m;i++)if(b[id][i]>0) upd(nu[b[id][i]]+1,qry(nu[b[id][i]])+1); int mx=0; for(int i=1;i<=cnt;i++)mx=max(mx,qry(i)); return mx; } int na[1010],nb[1010]; void solve(vector<int>v){ bool sp=false; for(int i=0;i<(int)v.size();i++){ int id=v[i]; for(int j=0;j<m;j++)if(a[id][j]==0)sp=true; } int cnt=0; for(int i=0;i<(int)v.size();i++){ int id=v[i]; for(int j=0;j<m;j++)if(a[id][j]>0)exist[a[id][j]]++,cnt++; for(int j=0;j<m;j++)if(b[id][j]>0)exist[b[id][j]]++; for(int j=0;j<m;j++)na[j]=a[id][j]; for(int j=0;j<m;j++)nb[j]=b[id][j]; for(int j=0;j<m;j++)if(a[id][j]>0&&exist[a[id][j]]<2)a[id][j]=0; for(int j=0;j<m;j++)if(b[id][j]>0&&exist[b[id][j]]<2)b[id][j]=0; ans-=solve(id); for(int j=0;j<m;j++)a[id][j]=na[j]; for(int j=0;j<m;j++)b[id][j]=nb[j]; for(int j=0;j<m;j++)if(a[id][j]>0)exist[a[id][j]]--; for(int j=0;j<m;j++)if(b[id][j]>0)exist[b[id][j]]--; } // putchar('\n'); ans+=cnt; if(!sp){ if(!spare){ putchar('-'); putchar('1'); exit(0); } else ans++; } } int main(){ // freopen("test.txt","r",stdin); n=read();m=read(); for(int i=0;i<n;i++)for(int j=0;j<m;j++)a[i][j]=read(); for(int i=0;i<n;i++)for(int j=0;j<m;j++)b[i][j]=read(); for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(a[i][j]==0)spare=true; for(int i=0;i<n;i++){ bool flag=true; int cnt=0; for(int j=0;j<m;j++){ if(a[i][j]>0){ exist[a[i][j]]=true; cnt++; } } for(int j=0;j<m;j++){ if(b[i][j]>0){ if(!exist[b[i][j]]) flag=false; else exist[b[i][j]]=false; } } for(int j=0;j<m;j++){ if(exist[a[i][j]]){ flag=false; exist[a[i][j]]=false; } } if(flag){ ok[i]=true; int tmp=cnt-solve(i); ans+=tmp; if(cnt==m&&tmp!=0){ if(!spare){ putchar('-'); putchar('1'); return 0; } else ans++; } } } // for(int i=0;i<n;i++)print(ok[i]),putchar(' '); // putchar('\n'); for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(a[i][j]>0&&(!ok[i]))pos[a[i][j]]=i; for(int i=0;i<n;i++)for(int j=0;j<m;j++){ if(b[i][j]>0&&(!ok[i])&&pos[b[i][j]]!=i){ // print(pos[b[i][j]]);putchar(' ');print(i);putchar('\n'); g[pos[b[i][j]]].push_back(i); g[i].push_back(pos[b[i][j]]); } } for(int i=0;i<n;i++)if((!ok[i])&&(!vis[i])){ v.clear(); dfs(i); // for(int j=0;j<(int)v.size();j++)print(v[j]),putchar(' '); solve(v); } print(ans); return 0; } /*inline? ll or int? size? min max?*/
- 1
信息
- ID
- 7129
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者