首页 > 其他分享 >[题解]CF1223F Stack Exterminable Arrays

[题解]CF1223F Stack Exterminable Arrays

时间:2024-06-24 12:34:17浏览次数:30  
标签:Trie int 题解 ll 会加 Arrays 编号 CF1223F 节点

CCF 出的原题观摩一下。

思路

首先可以用一个 Trie 来维护。

在这里对本文中的一些变量做一下说明。

  1. \(p\) 表示当前维护的 Trie 中,指向的元素编号。
  2. \(t_i\) 表示在 Trie 中编号为 \(i\) 的元素在原序列中的值。
  3. \(f_i\) 表示在 Trie 中编号为 \(i\) 的元素在 Trie 中的父节点。
  4. \(v_i\) 表示在 Trie 中编号为 \(i\) 被遍历的次数。

考虑每一次将一个数 \(a_i\) 加入 Trie 的时候需要做什么操作。

如果当前在 Trie 中指向的节点 \(t_p\) 与 \(a_i\) 相等,说明可以进行合并, 那么直接将 \(p\) 跳到 \(f_p\) 即可;否则需要新开一个节点 \(v\),接在 \(p\) 的下方,并将 \(p\) 更新到 \(v\) 上。

然后在更新 \(p\) 之后,要将 \(v_p\) 加 \(1\)。

考虑如何统计答案。发现点 \(p\) 被遍历过 \(2\) 次时,答案会加 \(1\);\(3\) 次,答案会加 \(2\);以此类推。

这是因为当 \(v_p > 1\) 时,说明 \(p\) 节点已经可以被合并 \(v_p - 1\) 次了,所以直接加 \(v_p - 1\) 即可。

注意:在代码中为了优美,将 \(v_p\) 初值设为了 \(-1\)。

但是用普通的 Trie 显然是过不了的,因为 Trie 的空间复杂度在本题中会变为 \(\Theta(n^2)\),所以直接开一个 umap 即可。

复杂度为 \(\Theta(n \log n)\),实测跑得飞快。

Code

#include <bits/stdc++.h>  
#define re register  
#define ll long long  
  
using namespace std;  
  
const int N = 3e5 + 10;  
int T,n,p,idx;  
ll ans;  
int arr[N];  
  
struct node{  
    ll val;  
    int u,fa;  
    unordered_map<int,int> son;  
}tr[N];  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline void solve(){  
    ans = 0;  
    p = idx = 1;  
    n = read();  
    for (re int i = 1;i <= n;i++){  
        tr[i].val = tr[i].u = tr[i].fa = 0;  
        tr[i].son.clear();  
        arr[i] = read();  
    }  
    for (re int i = 1;i <= n;i++){  
        if (arr[i] == tr[p].u) p = tr[p].fa;  
        else{  
            int v;  
            if (!tr[p].son.count(arr[i])){  
                tr[p].son[arr[i]] = v = ++idx;  
                tr[v] = {-1,arr[i],p};  
            }  
            else v = tr[p].son[arr[i]];  
            p = v;  
        }  
        tr[p].val++;  
        ans += tr[p].val;  
    }  
    printf("%lld\n",ans);  
}  
  
int main(){  
    T = read();  
    while (T--) solve();  
    return 0;  
}  

标签:Trie,int,题解,ll,会加,Arrays,编号,CF1223F,节点
From: https://www.cnblogs.com/WaterSun/p/18264793

相关文章

  • [题解]CF1175E Minimal Segment Cover
    思路这是一道简单的DP题,DP题的核心就是状态转移。先来说一说\(dp\)数组的含义。\(dp_{i,j}\)表示从\(i\)这个点用\(2^j\)条线段能走到的最远的点。我们再来考虑一下边界情况。因为我们只用\(2^0\)条线段,那么:\(dp_{i,0}=\max(dp_{i,0},r)\)接着,我们递推一......
  • [题解]CF1092D1 Great Vova Wall (Version 1)
    思路发现,如果相邻元素的奇偶性相同,那么一定能通过在较低的位置竖着放若干个如果在\(i\)的位置竖着放一块砖头,使得这两列的高度相同。那么,我们想到直接考虑\(h_i\)的奇偶性,即将\(h_i\leftarrowh_i\bmod2\)。如果\(h_i=h_{i+1}\),我们显然可以同时使\(h_i\)和\(h......
  • [题解]CF1070C Cloud Computing
    思路考虑用线段树维护区间信息:价格在\([l,r]\)之间的CPU的数量。购买所有价格在\([l,r]\)之间CPU所需的钱。容易将区间修改转化为差分,从而实现单点修改。于是可以使用\(n\)个vector存储第\(i\)天所需进行的修改。查询第\(i\)天的答案时,如果不足\(k\)......
  • [题解]CF1746B Rebellion
    思路首先我们需要看到题目一个特殊的地方:这个序列中只存在\(0\)和\(1\)。那么,我们不难发现最终的答案一定是形如下面的序列:\(0,\dots,0,1,\dots,1\)。知道了这些,就很好想了。我们从后往前枚举,如果当前一位为\(0\)了,就从\(last\simi\)扫一遍,如果有\(1\)将最靠前的\(......
  • [题解]CF1742G Orray
    思路做这道题之前,首先要知道一个性质:\(a\operatorname{or}b\geqa\)。那么,我们就能得出一个结论:经过一定顺序的排列,最多经过\(\lceil\log_2^{a_{\max}}\rceil\)个数就能让前缀或的值达到最大值。我们不妨令有一个位置\(i\),\(b_1,b_2,\dots,b_{i-1}\)单调递增,而\(b_i......
  • [题解]CF1742E Scuza
    2022/11/23:修改了一下代码。题意有\(T\)组数据,每次给出一个\(n,q\),表示台阶的数量和询问的次数。然后再给出一个\(a_i\)为台阶高度的差分数组。每次询问给出一个\(k\),表示每次能走\(k\)个单位的高度。问:最高能到达的高度。思路考虑暴力,我们知道了高度的差分数组,那......
  • [题解]CF1741D Masha and a Beautiful Tree
    思路我们可以观察样例,不难发现:对于任意一段长度为\(2^k\)的区间中,如果最大值减最小值加\(1\)等于此区间的长度,那么一定有解。因为,我们的目标是使整个序列升序排列。因此,我们在一个区间内的最大值减最小值加\(1\)与区间长度是相等的。所以,我们可以用上述结论为判断无解的......
  • [题解]CF1741B Funny Permutation
    思路简单构造题,我们可以分为三种情况进行构造。\(n=3\)时,一定无解,输出-1。(你可以试试)\(n\bmod2=1\wedgen\neq3\)时,我们直接先输出\(n,n-1\),然后顺序输出即可。证明:令\(a\)为最后构造出的序列。那么,\(a_1=n,a_2=n-1,a_i=i-2(3\leqi\leq......
  • [题解]CF1732C2 Sheikh (Hard Version)
    思路首先证明一下当序列扩大时答案一定不劣。考虑\(f(l,r)\)到\(f(l,r+1)\)的变化。\[\begin{aligned}f(l,r)-f(l,r+1)&=s_{l,r}-xs_{l,r}-s_{l,r+1}+xs_{l,r+1}\\&=xs_{l,r+1}-xs_{l,r}-a_{r+1}\\&......
  • fdisk时WARNING: Re-reading the partition table failed with error 16: 设备或资源
    WARNING:Re-readingthepartitiontablefailedwitherror16:设备或资源现象:划分磁盘有警告, WARNING:Re-readingthepartitiontablefailedwitherror16:设备或资源忙.Thekernelstillusestheoldtable.Thenewtablewillbeusedatthenextrebootoraft......