牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)

牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)

链接:https://ac.nowcoder.com/acm/problem/15706

现在需要您来帮忙维护这个名册,支持下列 4 种操作:

  1. 插入新人名 si,声望为 a
  2. 给定名字前缀 pi 的所有人的声望值变化 di
  3. 查询名字为 sj 村民们的声望值的和(因为会有重名的)
  4. 查询名字前缀为 pj 的声望值的和

题解:一个非常明显的线段树操作,前缀可以看作是区间更新,区间查询,给定名字就是单点更新,单点查询,字典树上dfs序可以得到将树型结构变成一个线性的结构,然后用线段树维护即可,比较好的码力题了
/**
*        ┏┓    ┏┓

  •        ┏┛┗━━━━━━━┛┗━━━┓
  •        ┃       ┃  
  •        ┃   ━    ┃
  •        ┃ >   < ┃
  •        ┃       ┃
  •        ┃... ⌒ ...  ┃
  •        ┃       ┃
  •        ┗━┓   ┏━┛
  •          ┃   ┃ Code is far away from bug with the animal protecting          
  •          ┃   ┃ 神兽保佑,代码无bug
  •          ┃   ┃           
  •          ┃   ┃       
  •          ┃   ┃
  •          ┃   ┃           
  •          ┃   ┗━━━┓
  •          ┃       ┣┓
  •          ┃       ┏┛
  •          ┗┓┓┏━┳┓┏┛
  •           ┃┫┫ ┃┫┫
  •           ┗┻┛ ┗┻┛
    */
    // warm heart, wagging tail,and a smile just for you!
    //
    // ooOoo
    // o8888888o
    // 88" . "88
    // (| -- |)
    // O  = /O
    //
    _/---'\____ // .' \| |//.
    // / ||| : |||// // / ||||| -:- |||||- // | |   - /// | |
    // | _| ''---/'' | |
    //   .-_
    -
    _/-. /
    // . .' /--.--\. .
    // ."" '< .___\_<|>_/___.' >'"". // | | :- `.;\ _ /;./ - : | |
    //    -. \_ __\ /__ _/ .- / /
    // ======-.____-.
    ___/_.-____.-'====== //=---='
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    // 佛祖保佑 永无BUG

    include

    include

    include

    include

    include

    include

    include

    include

    include

    include

    include

    using namespace std;
    typedef long long LL;
    typedef pair pii;
    typedef unsigned long long uLL;

    define ls rt<<1

    define rs rt<<1|1

    define lson l,mid,rt<<1

    define rson mid+1,r,rt<<1|1

    define bug printf("*********\n")

    define FIN freopen("input.txt","r",stdin);

    define FON freopen("output.txt","w+",stdout);

    define IO ios::sync_with_stdio(false),cin.tie(0)

    define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"

    define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"

    define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<

    const int maxn = 3e5 + 5;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const double Pi = acos(-1);
    LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
    }
    LL lcm(LL a, LL b) {
    return a / gcd(a, b) * b;
    }
    double dpow(double a, LL b) {
    double ans = 1.0;
    while(b) {
    if(b % 2)ans = ans * a;
    a = a * a;
    b /= 2;
    } return ans;
    }
    LL quick_pow(LL x, LL y) {
    LL ans = 1;
    while(y) {
    if(y & 1) {
    ans = ans * x % mod;
    } x = x * x % mod;
    y >>= 1;
    } return ans;
    }
    struct Trie {
    int nxt[maxn][26], tot;
    int in[maxn], out[maxn], time_tag;
    void init() {
    memset(nxt, 0, sizeof(nxt));
    tot = 1;
    time_tag = 0;
    }
    void insert(string str) {
    int p = 1;
    int len = str.length();
    for(int i = 0; i < len; i++) {
    int ch = str[i] - 'a';
    if(!nxt[p][ch]) {
    nxt[p][ch] = ++tot;
    }
    p = nxt[p][ch];
    }
    }
    int query(string str) {
    int p = 1;
    int len = str.length();
    for(int i = 0; i < len; i++) {
    int ch = str[i] - 'a';
    if(!nxt[p][ch]) {
    return 0;
    }
    p = nxt[p][ch];
    }
    return p;
    }
    void dfs(int u) {
    in[u] = ++time_tag;
    for(int i = 0; i < 26; i++) {
    if(nxt[u][i]) {
    dfs(nxt[u][i]);
    }
    }
    out[u] = time_tag;
    }
    } trie;
    LL sum[maxn << 2];
    int lazy[maxn << 2];
    int cnt[maxn << 2];
    void push_up(int rt) {
    sum[rt] = sum[ls] + sum[rs];
    cnt[rt] = cnt[ls] + cnt[rs];
    }
    void build(int l, int r, int rt) {
    sum[rt] = lazy[rt] = 0;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    }
    void push_down(int rt, int len) {
    if(lazy[rt]) {
    lazy[ls] += lazy[rt];
    lazy[rs] += lazy[rt];

     sum[ls] += lazy[rt] * cnt[ls];
     sum[rs] += lazy[rt] * cnt[rs];
    
     lazy[rt] = 0;

    }
    }
    void update_pos(int pos, int val, int l, int r, int rt) {
    if(l == r) {
    sum[rt] += val;
    cnt[rt]++;
    return;
    }
    int mid = (l + r) >> 1;
    push_down(rt, r - l + 1);
    if(pos <= mid) update_pos(pos, val, lson);
    else update_pos(pos, val, rson);
    push_up(rt);
    }
    void update(int L, int R, int val, int l, int r, int rt) {
    if(L <= l && r <= R) {
    sum[rt] += cnt[rt] * val;
    lazy[rt] += val;
    return;
    }
    int mid = (l + r) >> 1;
    push_down(rt, r - l + 1);
    if(L <= mid) update(L, R, val, lson);
    if(R > mid) update(L, R, val, rson);
    push_up(rt);
    }
    LL query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) {
    return sum[rt];
    }
    int mid = (l + r) >> 1;
    push_down(rt, r - l + 1);
    LL ans = 0;
    if(L <= mid) ans += query(L, R, lson);
    if(R > mid) ans += query(L, R, rson);
    return ans;
    }
    int op[maxn];
    char buf[maxn];
    string str[maxn];
    int val[maxn];
    int main() {

    ifndef ONLINE_JUDGE

    FIN

    endif

    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
    scanf("%d %s", &op[i], buf);
    str[i] = buf;
    if(op[i] <= 2) {
    scanf("%d", &val[i]);
    }
    }
    trie.init();
    for(int i = 1; i <= n; i++) {
    if(op[i] == 1) {
    trie.insert(str[i]);
    // cout << str[i] << endl;
    }
    }
    trie.dfs(1);
    // bug;
    int tot = trie.tot;
    // debug1(tot);
    build(1, tot, 1);
    for(int i = 1; i <= n; i++) {
    if(op[i] == 1) {
    int u = trie.query(str[i]);
    int pos = trie.in[u];
    // debug1(pos);
    update_pos(pos, val[i], 1, tot, 1);
    // bug;
    } else if(op[i] == 2) {
    int u = trie.query(str[i]);
    if(u) {
    int l = trie.in[u];
    int r = trie.out[u];
    update(l, r, val[i], 1, tot, 1);
    }
    } else if(op[i] == 3) {
    int u = trie.query(str[i]);
    if(u) {
    int l = trie.in[u];
    int r = trie.in[u];
    LL ans = query(l, r, 1, tot, 1);
    printf("%lld\n", ans);
    } else {
    printf("0\n");
    }
    } else if(op[i] == 4) {
    int u = trie.query(str[i]);
    if(u) {
    int l = trie.in[u];
    int r = trie.out[u];
    LL ans = query(l, r, 1, tot, 1);
    printf("%lld\n", ans);
    } else {
    printf("0\n");
    }

     }

    }
    return 0;
    }

你可能感兴趣的:(牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树))