通达世海 發表於 2025-11-22 20:01:00

洛谷-P5658 [CSP-S 2019] 括号树 题解

<p>值域线段树 + 离线的 <span class="math inline">\(O(n\log n)\)</span> 做法。</p>
<h2 id="题目大意">题目大意</h2>
<p>给定一棵树,每个节点有一个括号。对于每个节点 <span class="math inline">\(i\)</span>,定义 <span class="math inline">\(s_i\)</span> 为从根节点到 <span class="math inline">\(i\)</span> 的路径上所有括号按顺序组成的字符串。求每个 <span class="math inline">\(s_i\)</span> 中互不相同的合法括号子串的个数 <span class="math inline">\(k_i\)</span>。</p>
<h2 id="思路">思路</h2>
<p>首先,<span class="math inline">\(k_i\)</span> 可以从父节点递推得到,<span class="math inline">\(k_i=k_{f_i}+a_i\)</span>。其中 <span class="math inline">\(a_i\)</span> 为以节点 <span class="math inline">\(i\)</span> 结尾的合法括号序列数量。因此只要求出每个节点的 <span class="math inline">\(a\)</span>。</p>
<p>经典技巧,将 <span class="math inline">\(\texttt{(}\)</span> 的权值设为 <span class="math inline">\(1\)</span>,<span class="math inline">\(\texttt{)}\)</span> 设为 <span class="math inline">\(−1\)</span> ,做树上前缀和。设点 <span class="math inline">\(u\)</span> 的前缀和为 <span class="math inline">\(sum_u\)</span>。则以 <span class="math inline">\(u\)</span> 结尾的合法括号子串的开头 <span class="math inline">\(v\)</span> 必须满足:</p>
<ol>
<li><span class="math inline">\(sum_{f_v}=sum_u\)</span>。</li>
<li>对于 <span class="math inline">\(v\to u\)</span> 这条链上的所有点 <span class="math inline">\(x\)</span>,有 <span class="math inline">\(sum_x\ge sum_u\)</span>。</li>
</ol>
<p>在 DFS 过程中开一棵值域线段树维护 <span class="math inline">\(1\to u\)</span> 这条链上每个 <span class="math inline">\(sum\)</span> 值对应的最大节点深度。这样就能找到 <span class="math inline">\(sum_p&lt;sum_u\)</span> 且深度最大的节点 <span class="math inline">\(p\)</span>。</p>
<p>设 <span class="math inline">\(ask(x,y)\)</span> 表示 <span class="math inline">\(1\to x\)</span> 链上 <span class="math inline">\(sum=y\)</span> 的节点数量。则 <span class="math inline">\(a_u=ask(f_u,k)-ask(p,k)\)</span>。</p>
<p>第一遍 DFS 求出所有询问并离线下来。</p>
<p>第二遍 DFS 求出所有点的 <span class="math inline">\(a\)</span>。</p>
<p>第三遍 DFS 对 <span class="math inline">\(a\)</span> 做树上前缀和得到所有点的 <span class="math inline">\(k\)</span> 即可。</p>
<p>时间复杂度 <span class="math inline">\(O(n\log n)\)</span>。</p>
<h2 id="code">Code</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
#define rept(i,a,b) for(int i(a);i&lt;=b;++i)
#define ls(p) ((p)&lt;&lt;1)
#define rs(p) ((p)&lt;&lt;1|1)
#define eb emplace_back
#define int long long
using namespace std;
constexpr int N=5e5+5;
struct Query{
    int k,coef,id;
    // k:目标值
    // coef:贡献系数,1/-1
    // id:贡献给到的节点
    Query(int _k,int _coef,int _id):k(_k),coef(_coef),id(_id){}
};
struct SegTree{
    int t;
    void update(int p,int pl,int pr,int pos,int x){// 单点修改
      if(pl==pr) return void(t=x);
      int mid=pl+pr&gt;&gt;1;
      if(pos&lt;=mid) update(ls(p),pl,mid,pos,x);
      else update(rs(p),mid+1,pr,pos,x);
      t=max(t,t);
    }
    int query(int p,int pl,int pr,int l,int r){// 区间max
      if(l&gt;r) return 0;
      if(l&lt;=pl&amp;&amp;pr&lt;=r) return t;
      int mid=pl+pr&gt;&gt;1,a=0;
      if(l&lt;=mid) a=max(a,query(ls(p),pl,mid,l,r));
      if(mid&lt;r) a=max(a,query(rs(p),mid+1,pr,l,r));
      return a;
    }
}sgt;
char s;
int sum,dep,cnt,a,st;
int n,m,ans;
vector&lt;int&gt; g;
vector&lt;Query&gt; q;
void dfs1(int u){
    int lst=sgt.query(1,1,m,sum,sum);
    sgt.update(1,1,m,sum,dep);
    st]=u;
    for(int v:g){
      sum=sum+(s=='('?1:-1);
      dep=dep+1;
      if(s==')'){
            int bound=sgt.query(1,1,m,1,sum-1);
            q.eb(sum,1,v);
            if(bound) q].eb(sum,-1,v);
      }
      dfs1(v);
    }
    sgt.update(1,1,m,sum,lst);
}
void dfs2(int u){
    ++cnt];
    for(Query x:q){
      a+=x.coef*cnt;
    }
    for(int v:g) dfs2(v);
    --cnt];
}
void dfs3(int u){
    for(int v:g){
      a+=a;
      dfs3(v);
    }
    ans^=u*a;
}
signed main(){
    cin.tie(0)-&gt;sync_with_stdio(0);
    cin&gt;&gt;n&gt;&gt;s+1;
    m=n&lt;&lt;1;
    rept(i,2,n){
      int x;cin&gt;&gt;x;
      g.eb(i);
    }
    g.eb(1);
    sum=n,dep=1;// 为了不出负数,sum统一加上n
    dfs1(0),dfs2(0),dfs3(0);
    cout&lt;&lt;ans;
    return 0;
}
</code></pre><br><br>
来源:https://www.cnblogs.com/xiaoniu142857/p/19258500
頁: [1]
查看完整版本: 洛谷-P5658 [CSP-S 2019] 括号树 题解