题目
题目要求:给定一个出入栈序列,要求寻找一个对应,使得任何一个时刻insert后,序列内的形态不同。
一个出入栈序列可以转化成一棵树(本菜鸡在这道题目学到的知识点,隐约记得PTA甲级上也有类似的题目,不过很简单,当时一下就过了),然后条件就是从根到每一个节点的链所构成的颜色序列两两不同。即每个点的儿子结点颜色各个不同,也就是树的每层上的结点颜色都不相同;要是相同了,就NO了。本菜鸡还学到了关于C++中容器vector的更多知识。
这道题目蛮有意思的,值得多去想一想。
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int vis[N], ans[N];
vector<int> record, G[N];
/*
push_back加入元素需要先构造然后拷贝或移动
emplace_back可以原地构造对象,然后加入到容器中,可以减少一次拷贝或构造
v.front();返回的是第一个元素的引用
v.back();返回的是最后一个元素的引用
int a=v.front();a并不是一个引用,改变a不会影响v.front()
int &b=v.front();对b的操作会影响v.front()
*/
int main()
{
int n;
cin>>n;
string s;
cin>>s;
int cnt=0;
record.emplace_back(0);
for(int i=0; i<2*n; i++){
if(s[i]=='('){//建树,模拟stack的进栈出栈的过程
cnt+=1;
G[record.back()].emplace_back(cnt);
record.emplace_back(cnt);
} else {
record.pop_back();
}
}
int x;
for(int i=0; i<n; i++){
scanf("%d", &x);
vis[x]+=1;//统计各种颜色的个数
}
priority_queue<pair<int, int> > que;
for(int i=1; i<=n; i++){
if(vis[i])
que.push({vis[i], i});//将颜色的个数与颜色值联系起来
}
for(int i=0; i<=n; i++){
if(G[i].size()>que.size()){//子结点个数大于颜色种类数,此时必有重复,这样保证同一个父结点下的子结点的颜色不会有重复
cout<<"NO"<<endl;
return 0;
}
vector<pair<int, int> > buffer;
for(auto v : G[i]){
ans[v]=que.top().second;
buffer.emplace_back(que.top());//用于记录该颜色的个数大于1的元素
que.pop();
}
for(auto v : buffer){
if(v.first>1){
que.push({v.first-1, v.second});//重新加入优先队列
}
}
}
cout<<"YES"<<endl;
for(int i=1; i<=n; i++){
cout<<ans[i];
if(i!=n)
cout<<" ";
else
cout<<"\n";
}
return 0;
}