2021-08-19

这篇博客介绍了如何通过构建树结构来分析出入栈序列,并使用C++中的容器vector解决一个判断题目的算法。题目要求保证树的每一层节点颜色不同,通过模拟栈操作和优先队列实现颜色分配,确保无重复。博客还探讨了vector的高效操作如emplace_back和front/back的使用。
摘要由CSDN通过智能技术生成

题目
题目要求:给定一个出入栈序列,要求寻找一个对应,使得任何一个时刻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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值