Wannafly挑战赛14 前缀查询(带前缀查询,修改字典树)

链接:https://www.nowcoder.com/acm/contest/81/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

思路:
这题明显就是字典树啦,然后带前缀的修改和查询,写成线段树那样就行了
accode

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int n;
const int maxn =5e6+42;
char s[maxn];
LL cnt;
struct node
{
    LL edans;
    LL edcnt;
    LL cnt;
    LL ans;
    int Nxt[27];
    LL lazy;
    void init()
    {
        edans = 0;
        edcnt = 0;
        cnt = 0;
        ans = 0;
        lazy = 0;
        memset(Nxt,-1,sizeof(Nxt));
    }
}Tire[maxn];
void push_up(int rt)
{
    Tire[rt].cnt = Tire[rt].edcnt;
    Tire[rt].ans = Tire[rt].edans;
    for(int i = 0;i<26;i++){
        if(Tire[rt].Nxt[i]!=-1){
            Tire[rt].ans += Tire[Tire[rt].Nxt[i]].ans;
            Tire[rt].cnt += Tire[Tire[rt].Nxt[i]].cnt;
        }
    }
}
void push_down(int rt)
{
    if(Tire[rt].lazy==0) return ;
    for(int i = 0;i<26;i++){
         if(Tire[rt].Nxt[i]!=-1){
            Tire[Tire[rt].Nxt[i]].lazy += Tire[rt].lazy;
             Tire[Tire[rt].Nxt[i]].ans += Tire[rt].lazy*Tire[Tire[rt].Nxt[i]].cnt;
              Tire[Tire[rt].Nxt[i]].edans += Tire[rt].lazy*Tire[Tire[rt].Nxt[i]].edcnt;
        }
    }
    Tire[rt].lazy = 0;
}
void Insert(int rt,int len,int pos,LL va)
{
    if(pos==len)
    {
        Tire[rt].edcnt++;
        Tire[rt].edans+=va;
        Tire[rt].cnt++;
        Tire[rt].ans+=va;
        return ;
    }
    push_down(rt);
    int to = Tire[rt].Nxt[s[pos]-'a'];
    if(to!=-1){


    }
    else{
        Tire[rt].Nxt[s[pos]-'a'] = ++cnt;
        to = cnt;
        Tire[to].init();
    }
     Insert(to,len,pos+1,va);
    push_up(rt);
}
void update(int rt,int len,int pos,LL va)
{
   if(pos==len)
   {
        Tire[rt].ans += Tire[rt].cnt*va;
        Tire[rt].edans += Tire[rt].edcnt*va;
        Tire[rt].lazy += va;
        return ;
   }
   push_down(rt);
    int to = Tire[rt].Nxt[s[pos]-'a'];
    if(to!=-1){
        update(to,len,pos+1,va);
        push_up(rt);
    }
}
LL query1(int len)
{
    int now = 0;
    for(int i =0;i<len;i++){
        int to = Tire[now].Nxt[s[i]-'a'];
        if(to==-1) return 0;
        push_down(now);
        now = to;
    }
    return Tire[now].edans;
}
LL query2(int len)
{

    int now = 0;
    for(int i =0;i<len;i++){
        int to = Tire[now].Nxt[s[i]-'a'];
        if(to==-1) return 0;
        push_down(now);
        now = to;
    }
    return Tire[now].ans;
}
int main()
{
    scanf("%d",&n);
    Tire[0].init();
    for(int i = 0;i<n;i++){
        int op;;
        LL va;
        scanf("%d",&op);
        if(op<=2){
            scanf("%s%lld",s,&va);
            int len = strlen(s);
            if(op==1){
                Insert(0,len,0,va);
            }
            else{
                update(0,len,0,va);
            }
        }
        else{
            scanf("%s",s);
            int len  = strlen(s);
            if(op==3){
               printf("%lld\n",query1(len));
            }
            else
            printf("%lld\n",query2(len));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/w571523631/article/details/80269638