zoukankan      html  css  js  c++  java
  • 牛客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<int, int> 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("********* ")

    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)<<"] "

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

    define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<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
    ", ans);
            } else {
                printf("0
    ");
            }
        } 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
    ", ans);
            } else {
                printf("0
    ");
            }
    
        }
    }
    return 0;
    

    }

  • 相关阅读:
    C# TCP异步服务/客户端
    Entity Framework Batch Update and Future Queries
    用c#编写socks代理服务器,大白话细述协议的最重要部分。
    ArraySegment AsEnumerable
    c#数据包拦截+网络编程
    为.Net Remoting增加基于SKYPE API的P2P传输通道
    如何看PDA的IP
    基本搞定PDA HTTP Server
    PDA SOAP Server探索历程(1)
    疑难问题之PDA SOAP Server
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/11645370.html
Copyright © 2011-2022 走看看