牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) include include include include include include include include include include include 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

牛客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

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 IO ios::sync_with_stdio(false),cin.tie(0)

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;

}