Codeforces 1136D - Nastya Is Buying Lunch - [贪心+链表+map]
题目链接:https://codeforces.com/problemset/problem/1136/D
题意:
给出 1 \sim n 的某个排列 p,再给出若干 (x,y) 表示当序列中出现 x,y 时,两者可以交换位置。问序列中最末尾的数可以前进多少步。
题解:
如果 p[n-1] 可以与 p[n] 交换位置,那么肯定是立刻交换,因为首先 p[n-1] 只能最多只能产生 1 步的贡献,同时就算把 p[n-1] 往前换,等到在未来某个时刻再跟 p[n] 交换,也不可能使得前进步数更多(自己画画就能明白),因此不如立刻换掉。
如果此时 p[n-1] 与 p[n] 不能交换位置,那么想要前进,必然要找一个能 p[x] 能和我 p[n] 交换的,和上面同样的道理,找远的 x 不会比找近的 x 更优,因此优先找最近的那个 p[x] 来跟我交换位置即可。
(这题的序列存储我用了数组模拟链表,时间复杂度是 O(n \log m),不知道我是不是写复杂了……)
AC代码:
#include<bits/stdc++.h> #define pb(x) push_back(x) using namespace std; const int maxn=3e5+10; const int maxm=5e5+10; int n,m; int a[maxn]; int head,tail,pre[maxn],nxt[maxn]; map<int,bool> mp[maxn]; bool check(int x,const vector<int>& v) { for(auto y:v) if(mp[x][y]==0) return 0; return 1; } int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin>>n>>m; nxt[head=0]=1, pre[tail=n+1]=n; for(int i=1;i<=n;i++) cin>>a[i], pre[i]=i-1, nxt[i]=i+1; for(int i=1,x,y;i<=m;i++) cin>>x>>y, mp[x][y]=1; vector<int> need; need.pb(a[n]); for(int x=pre[n];x>head;x=pre[x]) { if(check(a[x],need)) { int L=pre[x], R=nxt[x]; nxt[L]=R, pre[R]=L; } else need.pb(a[x]); } int cnt=0; for(int p=nxt[head];p<tail;p=nxt[p]) cnt++; cout<<n-cnt<<endl; }
转载请注明出处:https://dilthey.cnblogs.com/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步