回顧 做過的TRIE樹題

2021-07-04 02:06:45 字數 4037 閱讀 5814

【thusc2015】異或問題 (standard io)

time limits: 2000 ms  memory limits: 262144 kb  detailed limits  

description

給定長度為n的數列x=和長度為m的數列y=,令矩陣a中第i行第j列的值aij=xi xor  yj,每次詢問給定矩形區域i∈[u,d],j∈[l,r],找出第k大的aij。

input

第一行包含兩個正整數n,m,分別表示兩個數列的長度第二行包含n個非負整數xi;

第三行包含m個非負整數yj;

第四行包含乙個正整數p,表示詢問次數;

隨後p行,每行均包含5個正整數,用來描述一次詢問,每行包含五個正整數u,d,l,r,k,含義如題意所述。

output

共p行,每行包含乙個非負整數,表示此次詢問的答案。

sample input

3 31 2 4

7 6 5

31 2 1 2 2

1 2 1 3 4

2 3 2 3 4

sample output65

1data constraint

對於100%的資料,0<=xi,yj<2^31,

1<=u<=d<=n<=1000,

1<=l<=r<=m<=300000,

1<=k<=(d-u+1)*(r-l+1),

1<=p<=500

其中,部分測試資料有如下特徵(互不包含):

對於5%的資料,滿足1<=m<=1000, 1<=p<=10, k=1;

對於15%的資料,滿足1<=m<=3000, 1<=p<=200;

對於20%的資料,滿足p=1;

對於30%的資料,滿足k=1;

對於其餘30%的資料,沒有其他特徵。

可持久化trie

可以發現n較小,m較大,考慮對m這一維建可持久化trie樹。

對於每乙個詢問,線性地掃n那一維,記錄每一二進位制位的0、1總個數。

再高位向低位列舉,在trie樹上跳。做法和可持久化線段樹上找k大值相似。

#include

#include

#include

using namespace std ;

#define n 1010

#define m 300010

#define mx 30

int n,m,p,a[n],b[m],rot[n],t,pos[2][n],ans[n],a[2] ;

struct node tr[5458385*2] ;

void update( int po )

void ins( int va , int &po , int dep )

if( ( ( 1 << dep ) & va ) ) ins( va , tr[po].r , dep-1 ) ;

else ins( va , tr[po].l , dep-1 ) ;

update( po ) ;

}int ask( int pos , bool h )

void nexjump( bool bit , int &pos , bool h )

int main()

scanf("%d",&p ) ;

while( p-- )

for( int i=mx ; i>=0 ; i-- )

if( a[1] - a[0] >= k ) ans[i] = 1 ;

else ans[i] = 0 , k-=a[1]-a[0] ;

for( int j=u ; j<=d ; j++ )

} int ret = 0 ;

for( int i=0 ; i<=mx ; i++ ) ret += ans[i] * ( 1 << i ) ;

printf("%d\n",ret ) ;

}}

【wintercamp 2013】單詞查詢 (standard io)

time limits: 2000 ms  memory limits: 65536 kb  detailed limits  

goto problemset

description

兩個單詞的最長公共字首是從第乙個字元開始的最長的相同字串,例如「identity」和「idealistic」的最長公共字首為「ide」。

乙個資料庫裡有n個單詞,在資料庫中查詢單詞w採用的演算法是非常原始的,把資料庫裡的單詞逐個跟w比較,兩個單詞逐個字元比較直到找到乙個不同的字元或某個單詞所有字元全部比較結束(此時可以斷定兩個單詞相同或某乙個單詞比另乙個要長),當找到w時,演算法結束。

分析上述演算法,查詢w需要的步數等於字元比較次數,把w與每個比較的單詞的最長公共字首的長度加起來的和就是答案。

程式設計計算查詢q個單詞,每個單詞所需的比較次數。

input

第一行包含乙個整數n(1<=n<=30000),表示資料庫中單詞的個數。

接下來n行按順序描述資料庫中的單詞,不會出現相同的單詞。

接下來包含乙個整數q(1<=q<=30000),表示需要查詢的單詞數量。

接下來q行,每行描述需要查詢的單詞。

所有的單詞都是由不超過30個英文小寫字母組成的字串。

output

每行輸出乙個整數,表示每個單詞查詢過程中的比較次數。

sample input

8majmunica

majmun

majka

malina

malinska

malo

maleni

malesnica

3krampus

malnar

majmun

sample output829

14hint

樣例2中查詢單詞「krampus」的比較次數為8,因為要跟資料庫中每個單詞的第乙個字元比較一次。

而查詢單詞「malnar」的時候,我們需要,前3個單詞都需要3次比較,接下來的5個單詞每個都需要4次比較,這樣一共29次。

查詢單詞「majmun」一共需要14次,對於資料庫中第乙個單詞「majmunica」,我們有6次成功的比較,還需一步判斷出「majmunica」比「majmun」要長,對於第二個單詞「majmun」,我們同樣有6次成功的比較,還需一步判斷出兩個單詞是完全相同的,所以整個比較結束,一共花了14次。

可持久化trie是會爆空間的,除非用二進位制壓位。

考慮字串雜湊+普普通通的trie

對於詢問的字串c,若它出現過,即存在s[i]=c,i若有多個取值,取最小值,答案必然為從字串1至i的比較次數。考慮在插入i這個字串時記錄它此時的答案存起來,在詢問時用。匹配用雜湊。

對於未出現過的,直接在trie上跳,即為答案。

#include

#include

#include

#include

#include

using namespace std ; #define n 30010 #define psb( x ) push_back( x ) #define iter vector< forvect >::iterator int n , q , i , j , k , st[n][2] , mo[2] = , cur[2] , t ; char s[40] ; typedef pair< int , int > p ; map< p , int > z ; struct forvect ; struct node tr[n*30] ; int tmp ; void ins( int n ) f[n*2] ;

struct trie tr[n*10] ;

int tot,rot[n] ;

void ins( int a , int b , str s )

return fa[a] ;

}int find_trie( int x , str s ) {

int len = strlen( s ) , i ;

x = rot[x] ;

for( i=0 ; i

trie字典樹 模板題

字典樹是一種實現字串快速檢索的多叉樹結構。每個節點都擁有很多個指標。1 include 2 include 3 using namespace std 4 5 const int n 1e6 5,m 5e5 5 6 7 int trie m 26 tot 0,cnt m 陣列模擬樹,8 cnt i ...

trie字典樹 模板題

字典樹是一種實現字串快速檢索的多叉樹結構。每個節點都擁有很多個指標。1 include 2 include 3 using namespace std 4 5 const int n 1e6 5,m 5e5 5 6 7 int trie m 26 tot 0,cnt m 陣列模擬樹,8 cnt i ...

trie字典樹acwing題組

農夫約翰在給他的奶牛們餵食時遇到了乙個問題。他共有 n 頭奶牛,編號 1 n 每次餵食前,這 n 頭奶牛會按照 1 n 的順序站成一排。此外,每頭奶牛都被分配了乙個可能不唯一的整數。那麼所有被分配的整數就形成了乙個長度為 n 的整數序列。請你在該整數序列中找出乙個連續的非空子序列,使得子串行中元素的...