zoukankan      html  css  js  c++  java
  • 括号树

    Get up where you tripped over.

    做一做CSPS2019,感受一下自己当时的愚蠢现在的愚蠢。

    很喜欢skyh的一句话:勇争第二吧,祝福你们。

    2019年11月16日上午9时许,我大概觉得想到了T2正解,于是开码,发现算法自身bug,GG等死

    2021年11月16日上午9时许,我大概觉得我又行了(不是),于是继续想T2,发现我是真的很愚蠢。

    我来陈述一下我的误区,大概是dfs到一个节点,现在就考虑从根到这个节点x有多少以x为结尾的括号序列。

    我当时的想法是,首先可以考虑前缀和为0,也就是查找从根到路径上的点i,使得sum[i]=sum[x],加上一个限制,就是从i到x上的所有点不能有sumj<sumi,防止出现“)(”这种情况

    实际上我的思路就是很不清晰的,也和没有逻辑,我应该考虑合法括号序列的等价条件是什么。当时觉得如果一个满足前缀和条件的sumi不能满足第二个限制,那么前面的点也不能满足,有一个单调性

    于是我就开始大力yy,想能不能查找得点都满足在一个点之后,然后我发现错了,然后就GG了

    但是这个思路是可以修正的,考虑事情一定要考虑清楚,把他的等价条件摆清楚,摆着摆着就会了

    现在就是一个点很小,所有在他之前的比他大的点都不能跨过他作为左端点,那就很明显是单调栈的思想,也就是这个很小的点弹掉了之前那些比他大的点,维护一个关于sum的单调栈从根节点到目前的x,除此之外,我现在要建立一个数据结构,要统计一个权值sum等于sumx的个数,我可以有log复杂度查询,那我现在就可以使用主席树,但是有些点是不行的,我可以直接跳过这些点建树,也就是说,我维护一个从根节点到x的主席树,方便我跳过某些版本来建树,跳过的那些版本对应的就是我单调栈内被弹掉的元素,剩下的都是一定能够作为左端点的元素,然后再查询这个集合里有sumx=sumi的个数,就行了。

    尽管不是最优的,但是出题人不是放了么

    也不是说这个做法有多好,只是有些坎过不去而已。

    #include<iostream>
    #include<cstdio>
    #include<vector>
    using namespace std;
    const int N=5e5+9;
    char s[N];
    int a[N],sum[N],pr[N],fa[N],rt[N],n,tt,root;
    long long f[N];
    vector<int>ve[N];
    struct tree
    {
    	int w,lc,rc;
    }tr[N*30];
    int rd()
    {
    	int s=0,w=1;
    	char cc=getchar();
    	for(;cc<'0'||cc>'9';cc=getchar()) if(cc=='-') w=-1;
    	for(;cc>='0'&&cc<='9';cc=getchar()) s=(s<<3)+(s<<1)+cc-'0';
    	return s*w;
    }
    void insert(int &k,int p,int l,int r,int w)
    {
    	k=++tt;
    	tr[k]=tr[p];
    	if(l==r){tr[k].w++;return;}
    	int mid=(l+r)>>1;
    	if(w<=mid) insert(tr[k].lc,tr[p].lc,l,mid,w);
    	else insert(tr[k].rc,tr[p].rc,mid+1,r,w);
    	tr[k].w=tr[tr[k].lc].w+tr[tr[k].rc].w;
    }
    int askp(int k,int l,int r,int w)
    {
    	if(l==r) return tr[k].w;
    	int mid=l+r>>1;
    	if(w<=mid) return askp(tr[k].lc,l,mid,w);
    	else return askp(tr[k].rc,mid+1,r,w);
    }
    void dfs1(int x)
    {
    	sum[x]=sum[fa[x]]+a[x];
    	int now=fa[x];
    	while(now&&sum[x]<sum[now]) now=pr[now];
    	if(now==0&&sum[x]<0)pr[x]=-1;
    	else pr[x]=now;
    	if(pr[x]>=0)insert(rt[x],rt[pr[x]],-n,n,sum[x]);
    	else insert(rt[x],root,-n,n,sum[x]);
    	if(a[x]==1) f[x]=f[fa[x]];
    	else
    		f[x]=f[fa[x]]+askp(rt[x],-n,n,sum[x])-1;
    	for(int i=0;i<ve[x].size();i++)
    	{
    		int y=ve[x][i];
    		if(y==fa[x]) continue;
    		dfs1(y);
    	}
    }
    int main()
    {
    	freopen("brackets.in","r",stdin);
    	freopen("brackets.out","w",stdout);
    	n=rd();root=tt++;
    	scanf("%s",s+1);
    	for(int i=1;i<=n;i++)
    	{
    		if(s[i]=='(') a[i]=1;
    		else a[i]=-1;
    	}
    	for(int i=2;i<=n;i++)
    	{
    		fa[i]=rd();
    		ve[fa[i]].push_back(i);
    	}
    	insert(rt[0],root,-n,n,0);
    	dfs1(1);
    	long long ans=0;
    	for(int i=1;i<=n;i++)ans^=(1ll*i*f[i]);
    	printf("%lld\n",ans);
    }
    /*
    d:
    g++ 1.cpp -o 1
    1.exe
    50
    
    ))()(())((((()))))))((())))()))((()(()((((((())())
    
    1 2 1 2 2 6 6 6 6 10 10 10 7 13 13 10 13 15 18 18 20 17 19 10 25 26 27 25 25 25 31 29 30 34 25 34 29 25 30 39 38 41 34 36 35 43 44 25 44
    
    */
    

      

    Zeit und Raum trennen dich und mich.时空将你我分开。
  • 相关阅读:
    Apicloud_(模板)登陆注册功能模板
    Apicloud_(接口验证)用户注册头部信息X-APICloud-AppKey生成
    Apicloud_(项目)网上书城02_后端数据获取
    Apicloud_(项目)网上书城01_前端搭建
    R_Studio(时序)Apriori算法寻找频繁项集的方法
    R_Studio(聚类)针对iris数据比较几种聚类方法优劣
    R_Studio(神经网络)BP神经网络算法预测销量的高低
    JavaWeb_(SSH论坛)_七、辅助模块
    JavaWeb_(SSH论坛)_六、点赞模块
    JavaWeb_(SSH论坛)_五、帖子模块
  • 原文地址:https://www.cnblogs.com/starsing/p/15614634.html
Copyright © 2011-2022 走看看