题解 | #Stack#
Stack
https://ac.nowcoder.com/acm/contest/11253/K
K题题解
法1: 构造拓扑关系
思路:先假设 我们要求的序列 a 为: 1、2、3、...... 、n
然后对序列 a 进行题目描述中的单调栈操作, 构造出满足 所给b[i] 的拓扑关系
拓扑关系:在这里 指位置间的拓扑关系 ,比如 pos1 指向 pos2 , 代表 a[pos1] 需大于 a[pos2]
Code 如下
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> PII; const int N = 1e6+10; PII p[N]; int a[N],b[N]; //如题 int to[N]; // to[i]:i指向to[i],拓扑关系 int in[N]; // 入度 int stk[N],q[N]; // 模拟栈、队列 int n,k; bool check(){ for(int i=0;i<k;i++){ int pos=p[i].first,val=p[i].second; int pp=p[i+1].first,vv=p[i+1].second; if(pos<val) return true; if(i==k-1) break; if(val+pp-pos<vv) return true; } return false; } void topsort(){ //求拓扑序 int hh=0,tt=-1; for(int i=1;i<=n;i++) if(!in[i]) q[++tt]=i; while(hh<=tt){ // 模拟队列 ps:个人偏爱于使用模拟队列求拓扑序,非必须 int t=q[hh++]; in[to[t]]--; if(in[to[t]]==0) q[++tt]=to[t]; } int t=n; for(int i=0;i<=tt;i++){ int pos=q[i]; a[pos]=t--; } // 输出序列 a for(int i=1;i<=n;i++) cout<<a[i]<<" \n"[i==n]; } void solve(){ int h=0; for(int i=1;i<=n;i++){ if(b[i]){ //b[i]确定,需满足b[i] bool u=false; while(h>b[i]-1) h--,u=true; //为了保证入栈后,栈中有b[i]个元素 if(u) to[stk[h+1]]=i; // 拓扑关系:a[stk[h+1]] > a[i] } // b[i]不确定,尽情入栈。不会与b[i]产生冲突 stk[++h]=i; to[i]=stk[h-1]; // 拓扑关系:a[i] > a[stk[h-1]] } for(int i=1;i<=n;i++) in[to[i]]++; topsort(); } int main(){ cin>>n>>k; for(int i=0;i<k;i++){ int pos,val; cin>>pos>>val; p[i]={pos,val}; b[pos]=val; } if(check()) puts("-1"); else solve(); return 0; }
法2 模拟
思路 参考 :https://blog.nowcoder.net/n/1a8897ea58004f15a93d0ee7009ac99a
Code 如下
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> PII; const int N = 1e6+10; PII p[N]; bool st[N]; int a[N]; int b[N]; int n,k; bool cmp(PII x,PII y){ int pos=x.first,val=x.second; int pp=y.first,vv=y.second; if(val==vv) return pos>pp; return val<vv; } bool check(){ for(int i=0;i<k;i++){ int pos=p[i].first,val=p[i].second; int pp=p[i+1].first,vv=p[i+1].second; if(pos<val) return true; if(i==k-1) break; if(val+pp-pos<vv) return true; } return false; } void solve(){ for(int i=0;i<k;i++){ int pos=p[i].first,val=p[i].second; int t=1; for(int j=pos-1;j>=1&&!st[j];j--) b[j]=max(1,val-t),t++; } for(int i=1;i<=n;i++) if(!b[i]) b[i]=b[i-1]; // 尾部要特殊处理 memset(p,0,sizeof p); for(int i=1;i<=n;i++) p[i]={i,b[i]}; sort(p+1,p+n+1,cmp); for(int i=1;i<=n;i++){ int pos=p[i].first; a[pos]=i; } for(int i=1;i<=n;i++) cout<<a[i]<<" \n"[i==n]; } int main(){ cin>>n>>k; for(int i=0;i<k;i++){ int pos,val; cin>>pos>>val; p[i]={pos,val}; st[pos]=true; b[pos]=val; } if(check()) puts("-1"); else solve(); return 0; }