Wannafly挑战赛14 B 字典树

B 前缀查询

题目描述
在一个 Minecraft 村庄中,村长有这一本小写字母构成的名册(字符串的表),
每个名字旁边都记录着这位村民的声望值,而且有的村民还和别人同名。
随着时间的推移,因为没有村民死亡,这个名册变得十分大。
现在需要您来帮忙维护这个名册,支持下列 4 种操作:

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

第一行为两个整数 0 ≤ N ≤ 105,表示接下来有 N 个操作;
接下来 N 行,每行输入一个操作,行首为一个整数 1 ≤ oi ≤ 4,表示这一行的操作的种类,
那么这一行的操作和格式为:

  1. 插入人名,这一行的格式为 1 si ai,其中 |ai| ≤ 103
  2. 前缀修改声望,这一行的格式为 2 pi di,其中 |di| ≤ 103
  3. 查询名字的声望和,这一行的格式为 3 sj
  4. 查询前缀的声望和,这一行的格式为 4 pj
    输入保证插入人名的字符串的长度和小于或等于 105,总的字符串的长度和小于或等于 106。

输出描述:

对于每一次询问操作,在一行里面输出答案。

示例1
输入

20
1 a -10
1 abcba -9
1 abcbacd 5
4 a
2 a 9
3 aadaa
3 abcbacd
4 a
3 a
2 a 10
3 a
2 a -2
2 d -8
1 ab -2
2 ab -7
1 aadaa -3
4 a
3 abcba
4 a
4 c

输出

-14
0
14
13
-1
9
11
1
11
0

tags:
裸裸的字典树,然后加个lazy 标记。

//https://www.nowcoder.com/acm/contest/81/B
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 2000005;

struct Item {
    ll  val1, val2, cnt1, cnt2, lazy;
} p[N*3];
int tr[N][27], Index;
char s[N];
void pushdown(int now) {
    rep(i,0,25) if(tr[now][i]) {
        int id = tr[now][i];
        p[id].val1 += p[now].lazy*p[id].cnt1;
        p[id].val2 += p[now].lazy*p[id].cnt2;
        p[id].lazy += p[now].lazy;
    }
    p[now].lazy = 0;
}
void Insert(ll x) {
    int len=strlen(s+1), now=0;
    for(int i=1; i<=len; ++i) {
        int id = s[i]-'a';
        if(tr[now][id]==0) tr[now][id] = ++Index;
        now = tr[now][id];
        if(p[now].lazy) pushdown(now);
        p[now].val1 += x,  ++p[now].cnt1;
    }
    p[now].val2 += x,  ++p[now].cnt2;
}
void update(ll x) {
    int len=strlen(s+1), now=0;
    for(int i=1; i<=len; ++i) {
        int id = s[i]-'a';
        if(tr[now][id]==0) tr[now][id] = ++Index;
        now = tr[now][id];
        if(p[now].lazy) pushdown(now);
    }
    int tnow = now;    now = 0;
    for(int i=1; i<=len; ++i) {
        now = tr[now][s[i]-'a'];
        p[now].val1 += x*p[tnow].cnt1;
    }
    p[now].lazy += x;
    p[now].val2 += x*p[now].cnt2;
}
ll  query1() {
    int len=strlen(s+1), now=0;
    for(int i=1; i<=len; ++i) {
        int id = s[i]-'a';
        if(tr[now][id]==0) return 0;
        now = tr[now][id];
        if(p[now].lazy) pushdown(now);
    }
    return p[now].val2;
}
ll  query2() {
    int len=strlen(s+1), now=0;
    for(int i=1; i<=len; ++i) {
        int id = s[i]-'a';
        if(tr[now][id]==0) return 0;
        now = tr[now][id];
        if(p[now].lazy) pushdown(now);
    }
    return p[now].val1;
}
int main()
{
    int T;  scanf("%d", &T);
    int type;  ll x;
    while(T--)
    {
        scanf("%d", &type);
        if(type==1) {
            scanf("%s%lld", s+1, &x);
            Insert(x);
        }
        else if(type==2) {
            scanf("%s%lld", s+1, &x);
            update(x);
        }
        else if(type==3) {
            scanf("%s", s+1);
            printf("%lld\n", query1());
        }
        else {
            scanf("%s", s+1);
            printf("%lld\n", query2());
        }
    }

    return 0;
}
posted @ 2018-05-10 15:13  v9fly  阅读(108)  评论(0编辑  收藏  举报