1. 程式人生 > >Wannafly挑戰賽14 字首查詢(帶字首查詢,修改字典樹)

Wannafly挑戰賽14 字首查詢(帶字首查詢,修改字典樹)

題目描述
在一個 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)); } } }