zoukankan      html  css  js  c++  java
  • [CSP-S]括号树

    题目

    题解

    本人语言能力有限,看代码可能更好理解,以下题解可跳过
    此题就是一系列恶心人的情况,你一一讨论出来就可以过了。
    PS:我的方法好像跟其他做法不太一样,各位请选择观看
    一般思路肯定就是一直搜下去。
    本人认为本题的最大难点就是它成功地匹配了一个,对总和ki的贡献值。
    首先看这一情况(()),这我们只能看作一个整体,因为在后面再加入一个(),它也不能用内部的括号
    新增的合格括号则对答案的贡献与之前连续整体的数量有关,这个不好描述
    看图(()))(()()(此时如果多加一个)则对总和ki的贡献值是3,算上它本身,还有前面两个括号组可以与它组合合法括号串
    而最前面的一堆合法括号串被隔开,显然不能够对答案进行贡献。
    确实很难描述,建议手动推一下
    我们拿pre数组表示离i结点最近是且未被匹配的祖先(或者它本身)
    num[i]表示遍历到i,当前连续整体的个数
    sum[i]则统计当前结点答案
    如果当前结点是(,sum就是父亲结点的值
    如果之前并不是整体,那么这个时候前面暂时就没有连续的点。
    如果是整体,那么num应该加1
    如果当前结点是)如果前面没有左括号,则sum,与num承接父亲
    如果有,那么sum就是要加上1,并且连续整体的数量
    同时pre,num数组需特殊更新(主要是实在描述不出来了,我太逊了)
    至于判断是否判断整体,我们用了flag。
    整体是个bfs。
    我的代码也是被很多大佬吊打

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<queue>
    #include<set>
    #define N 500005
    using namespace std;
    struct node{
    	int u,fg;
    	node(){};
    	node(int U,int F){
    		u = U,fg = F;
    	}
    };
    int n,fa[N],pre[N],num[N];
    long long ans,sum[N];
    char c[N];
    vector<int>G[N];
    void bfs(){
    	queue<node>Q;
    	Q.push(node(1,0));
    	while (!Q.empty()){
    		int u = Q.front().u,flag = Q.front().fg;
    		Q.pop();
    		for (int i = 0;i < G[u].size();i ++){
    			int v = G[u][i];	
    			bool flag1 = 0;
    			if (c[v] == '('){
    				sum[v] = sum[u];
    				pre[v] = v;
    				if (!flag || c[u] == '(')
    					num[v] = 0;
    				else if (flag)
    					num[v] = num[u] + 1;
    			}
    			else {
    				if(!pre[u]){
    					sum[v] = sum[u];
    					num[v] = num[u];
    				}
    				else {
    					sum[v] = sum[u] + 1 + num[pre[u]];
    					pre[v] = pre[fa[pre[u]]];
    					flag1 = 1;
    					num[v] = num[pre[u]];
    				}
    			}
    			ans = ans ^ (sum[v] * v);
    			Q.push(node(v,flag1));
    		}
    	}
    }
    int main(){
    	scanf ("%d
    ",&n);
    	for (int i = 1;i <= n;i ++)
    		scanf ("%c",&c[i]);
    	for (int i = 2;i <= n;i ++){
    		scanf ("%d",&fa[i]);
    		G[fa[i]].push_back(i);
    	}
    	if (c[1] == '(')
    		pre[1] = 1;
    	bfs();
    	printf("%lld
    ",ans);
    }
    }
    

    结语

    自己能力不强,考场做的题现在都推不出来。总之一句话:我菜炸了。
    自己真的是个菜逼,明明很显然的代码却是打得很复杂。

  • 相关阅读:
    DAY 169 创建虚拟环境05
    DAY 168 创建虚拟环境04
    DAY 167 创建虚拟环境03
    DAY 166 创建虚拟环境02
    java 内存区域
    java 内存机制
    JAVA GC
    JAVA根搜索算法
    mysql ---事务
    java lock -----锁
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566649.html
Copyright © 2011-2022 走看看