• 2021牛客暑期多校训练营10


    F Train Wreck

    这也是考场上自闭的题目....
    考虑栈中每个不同的状态,其实在瞎想中也想到了与图论的结合,但还是缺乏相同知识点之间的联系。如果我们考虑一个树的欧拉序的话,每个点进入时有一个标号,出来时还有一个标号。并且每个点都有这两个标号,这两个标号是一一匹配的。那这和括号匹配不就是一模一样的吗?那这道题根据括号匹配我们可以构造一棵树,...等等,本题中的括号可能构造出来的不是一个树而是一个森林,因为他可能多次出现栈为空的情况,没事我们额外加一个节点当做根节点。还这样的话就是一颗完整的树了。那题目中说到的每时每刻的栈的状态对应的是什么呢?同样考虑欧拉序的过程,其实栈中的元素都是该节点往上一直跳,直到根节点。那这样就明白了,我们要给每个点都染色,且每个点到根节点的颜色状态都不同,这样的话我们考虑一个节点x,对于x的所有儿子y而言,x到根节点的颜色对他们来说都是相同的前缀,要让他们不一样的话,只能是他们自己不一样,这样的我们就直接给他们染上不同的颜色即可。考虑染色的过程,一个颜色的数量越多显然是越不优的,所以我们染色时优先染数量多的颜色。这样之后,用不用考虑同一深度却不同父亲的节点呢?不用,因为父亲节点不同的话,在染父亲节点的时候,两个父亲节点的颜色已经不同了,所以只用考虑一个父亲节点所有的儿子即可。同一深度的就不用额外考虑了。

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define ls p<<1
    #define db double
    #define rs p<<1|1
    #define P 1000000007
    #define ll long long
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(x,y,z) for(int x=y;x<=z;++x)
    #define fep(x,y,z) for(int x=y;x>=z;--x)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=1e6+10;
    int n,cnt[N],Stack[N],top,num,ans[N],vis[N];
    char c[N<<1];
    bool flag=true;
    vector<int>son[N]; 
    priority_queue<pair<int,int> >q;
    
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    
    inline void dfs(int x)
    {
    	if(q.size()<son[x].size()) flag=false;
    	if(!flag) return;
    	priority_queue<pair<int,int> >d;
    	for(auto y:son[x])
    	{
    		ans[y]=q.top().second;
    		d.push({q.top().first-1,q.top().second});
    		q.pop();
    	}
    	while(d.size()) 
    	{
    		if(d.top().first>=1) q.push({d.top().first,d.top().second});
    		d.pop();
    	}
    	for(auto y:son[x]) dfs(y);
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
    	get(n);scanf("%s",c+1);
    	rep(i,1,n) cnt[read()]++;
    	rep(i,1,n<<1)
    	{
    		if(c[i]=='(')//进入一个新的节点. 
    		{
    			++num;
    			son[Stack[top]].push_back(num);
    			Stack[++top]=num;
    		}
    		else if(c[i]==')') --top;
    	}
    	rep(i,1,n)
    	{
    		if(cnt[i]&&!vis[i])
    		{
    			vis[i]=1;
    			q.push({cnt[i],i});
    		}
    	}
    	dfs(0);
    	if(!flag) puts("NO");
    	else
    	{
    		puts("YES");
    		rep(i,1,n) printf("%d ",ans[i]);
    	}
        return (0^_^0);
    }
    //以吾之血,铸吾最后的亡魂.
    
    
  • 相关阅读:
    vue路由
    vue-cli目录结构介绍
    andriodiphone视频禁止全屏播放
    JS判断Android、iOS或浏览器的多种方法(四种方法)
    vue中移动端自适应方案
    移动端视频不兼容
    vue之router-link
    移动端网页开发注意点
    AWS EC2服务器的HTTPS负载均衡器配置过程
    Kubernetes概念介绍和v1版本部署过程
  • 原文地址:https://www.cnblogs.com/gcfer/p/15160788.html
Copyright © 2020-2023  润新知