题解 | #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;
}