2 条题解

  • 2
    @ 2024-8-19 21:10:50
    #include <stack>
    #include <cstdio>
    using namespace std;
    
    int getbra()
    {
    	char c;
    	while((c=getchar())!='(' && c!=')')
    		;
    	return c=='(';
    }
    
    int beg[500005];
    int ed[500005];
    int nxt[500005];
    int top;
    
    void addedge(int a,int b)
    {
    	++top;
    	ed[top] = b;
    	nxt[top] = beg[a];
    	beg[a] = top;
    }
    
    stack<int> rb;    // 记录未匹配的右括号位置
    int rbi[500005];  // 方便还原
    int sufi[500005]; // 以这个位置结束的合法括号后缀的个数
    int pos;
    
    long long lastans;
    long long ins(int br)
    {
    	++pos;
    	if(br) //(
    	{
    		rb.push(pos);
    		rbi[pos] = sufi[pos] = 0;
    		return lastans;
    	}
    	else
    	{
    		if(rb.empty())
    		{
    			rbi[pos] = 0;
    			sufi[pos] = 0;
    			return lastans;
    		}
    		else
    		{
    			int r = rb.top();
    			rb.pop();
    
    			rbi[pos] = r;
    			sufi[pos] = sufi[r-1]+1; // 右括号前一个的合法后缀现在都是合法后缀,然后多一个单独一个的括号后缀
    			lastans += sufi[pos];
    			return lastans;
    		}
    	}
    }
    
    void erase(int br)
    {
    	if(br)
    	{
    		rb.pop();
    	}
    	else
    	{
    		if(rbi[pos])
    		{
    			rb.push(rbi[pos]);
    			lastans -= sufi[pos];
    		}
    	}
    	--pos;
    }
    
    int bri[500005];
    long long ansi[500005];
    
    void dfs(int x)
    {
    	ansi[x] = ins(bri[x]);
    
    	for(int p=beg[x]; p; p=nxt[p])
    	{
    		dfs(ed[p]);
    	}
    
    	erase(bri[x]);
    }
    
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1; i<=n; ++i)
    	{
    		bri[i] = getbra();
    	}
    	for(int i=2; i<=n; ++i)
    	{
    		int fa;
    		scanf("%d",&fa);
    		addedge(fa,i);
    	}
    
    	dfs(1);
    
    	long long ans = 0;
    	for(int i=1; i<=n; ++i)
    	{
    		ans ^= i*ansi[i];
    	}
    
    	printf("%lld\n",ans);
    }
    

    信息

    ID
    2
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    24
    已通过
    15
    上传者