题目链接
题目大意
有一个旧火车站,其只有一个死胡同轨道,可以视为一个栈,可以将火车入栈或者出栈。有 n ( 1 ≤ n ≤ 1 0 6 ) n(1\leq n\leq 10^6) n(1≤n≤106)彩色辆火车进站,第 i i i 辆火车的颜色是 k i ( 1 ≤ k i ≤ n ) k_i(1\leq k_i\leq n) ki(1≤ki≤n),进出栈顺序已定,现在你需要为每次入栈操作分配一辆火车,使得入栈时栈中其他火车颜色序列唯一。
题解
题目的要求就是在每次输入左括号的序列不能与之前的序列相同。
如果用数字表示输入左括号时的长度大小,当前的我们可以将样例
(
)
(
(
)
)
(
)
()(())()
()(())()变为
1121
1121
1121,可得我们需要保证三个1长度的颜色不相同。
再如
(
(
)
(
)
(
)
)
(()()())
(()()()),为
1222
1222
1222,我们需要保证三个2代表的其中第二个数字不相同,再观察一下图形,我们可以得出括号内相同层次的所代表的颜色不能相同,而之前的颜色是相同的。
你想到了什么?树的序列
通过举例,我们发现可以将其变为一棵树,要求是某个节点的所有子节点颜色不能相同。
只要颜色数满足所有非叶节点的子节点数,那么它就是可行的。
对于每个子节点,我们只需要优先选择颜色多的染色即可。
总结:
①我们需要建一棵树,表示其括号从属情况;
这里提供一种方法,对于每一个左括号,继续往右,若遇到长度小于等于它的左括号,
就起码遇到了一个右括号,跳出,不然,则是其子节点。
②对于每一个子节点,我们用优先队列选取较大的进行染色;
一起取出
−
1
-1
−1再一起放入,
如果染色的数量不够了,则输出“NO“。
参考代码
#include<bits/stdc++.h>
#define FOR(i,n,m) for(int i=n;i<=m;i++)
using namespace std;
void read(int &x)
{
int ret=0;
char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
ret=ret*10+c-'0',c=getchar();
x=ret;
}
const int N=1e6+5;
struct node{
int id,num;
}co[N];
priority_queue<pair<int,int>> q;
vector<int> v[N];
int n,t,t1;
int siz1[N],siz2[N],f[N],c[N];
int st[N],tt;
int s1=0;
void dfs(int x)
{
if(x==n)
return;
if(s1==n)
return;
FOR(i,s1+1,n)
{
if(siz1[i]<=siz1[x]) //不为其子节点
return;
s1=i;
v[x].push_back(i); //构树
dfs(i);
i=s1; //下一个
}
}
vector<pair<int,int>> va;
int check(int x)
{
if(v[x].size()==0)
return 1;
int s=0;
while(s<v[x].size()) //染色(一起放出)
{
if(q.empty())
return 0;
va.push_back(q.top()); //优先选择栈顶颜色多的
q.pop();
va[s].first--;
if(va[s].first<0)
return 0;
c[v[x][s]]=va[s].second;
s++;
}
s=0;
while(s<v[x].size()) //重新放入
q.push(va[s++]);
va.clear();
FOR(i,0,v[x].size()-1)
if(check(v[x][i])==0)
return 0;
return 1;
}
int main()
{
read(n);
FOR(i,1,2*n)
{
char c;
cin>>c;
if(c=='(')
siz1[++t]=++t1;
else
t1--;
}
FOR(i,1,n)
{
co[i].id=i;
co[i].num=0;
}
FOR(i,1,n)
{
if(siz1[i]==1)
{
s1=i;
dfs(i);
v[0].push_back(i); //对于长度为1的时候,我们设其父节点为0
i=s1; //下一个
}
}
FOR(i,1,n)
{
int x;
read(x);
co[x].num++; //统计颜色数量
}
// FOR(i,0,n)
// for(int j=0;j<v[i].size();j++)
// cout<<i<<" "<<v[i][j]<<endl;
FOR(i,1,n)
q.push(make_pair(co[i].num,co[i].id));
if(check(0)==0)
puts("NO");
else
{
puts("YES");
FOR(i,1,n)
printf("%d ",c[i]);
}
}