题目链接:hdu_5790_Prefix
题意:
给你n个字符串,字符串总长度不超过10W,然后给你一个区间,问你这个区间的字符串不相同的前缀有多少个。
题解:
由于z与上一个答案有关,所以强制在线,区间询问可以用主席树搞搞。
不同前缀的话,我们可以用一个trie来记录每一个节点的最晚出现时间,也就代表了这个前缀最晚出现的时间,然后保存到对应的主席树中。
这样就转换为询问区间不大于l的数有多少个。

1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 5 const int N=1e5+7; 6 char s[N]; 7 int root[N],tot,n,q; 8 struct node{int l,r,sum;}T[25*N]; 9 10 void update(int &x,int y,int pos,int l=1,int r=n) 11 { 12 T[++tot]=T[y],T[tot].sum++,x=tot; 13 if(l==r)return; 14 int m=l+r>>1; 15 if(pos<=m)update(T[x].l,T[y].l,pos,l,m); 16 else update(T[x].r,T[y].r,pos,m+1,r); 17 } 18 19 int query(int x,int y,int k,int l=1,int r=n) 20 { 21 if(l==r)return T[x].sum-T[y].sum; 22 int m=l+r>>1; 23 if(k<=m)return query(T[x].l,T[y].l,k,l,m); 24 else return T[T[x].l].sum-T[T[y].l].sum+query(T[x].r,T[y].r,k,m+1,r); 25 } 26 27 struct Trie{ 28 int tr[N][26],tot,mx[N]; 29 void nd(){mx[++tot]=0,memset(tr[tot],0,sizeof(tr[tot]));} 30 void init(){tot=-1,nd();} 31 void insert(char *s,int time) 32 { 33 int t1=root[time-1],t2; 34 for(int i=0,x=0;s[i]!='