1. 程式人生 > >BZOJ 十連測 可持久化字符串

BZOJ 十連測 可持久化字符串

div AR def 持久 復雜 post 線性復雜 sign 數組

SOL:

我們發現答案就是 跑一邊KMP 那麽答案就是i-net[i],

我們考慮在trie上跑KMP,我們發現KMP的復雜度是依賴攤還分析的線性復雜度。如果樸素的KMP做法時間復雜度是不對的。

比如這樣一個trie: a

|

a

|
a

/ \

b b

復雜度就退化了。那麽我們可以考慮對每一個節點開一個數組:

f[i] 記下當前的節點後查入i元素後的kmp值。

我們可以發現當前節點的f和其net的f是差不多的,只要將net的f copy一遍 ,再講net的後繼插進來就好了。

我們可以用主席樹來維護f

O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define sight(c) (‘0‘<=c&&c<=‘9‘)
#define N 300007
inline void read(int
&x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(int x){if (x<10) {putchar(0+x); return;} write(x/10); putchar(0+x%10);} inline void writeln(int x){ if (x<0) putchar(-),x*=-1; write(x); putchar(\n); } inline
void writel(int x){ if (x<0) putchar(-),x*=-1; write(x); putchar( ); } struct Node{ int l,r,x; }te[N<<5]; int tot,anw,n,m,op,fr,at,lastans,l,len[N],rot[N],fp[N],opt,Le; int f[N][21]; #define Mid (l+r>>1) void ins(int X,int & now,int l,int r,int id,int x) { now=++tot; te[now]=te[X]; if (id==Mid) {te[now].x=x;return;} if (id<Mid) ins(te[X].l,te[now].l,l,Mid-1,id,x); else ins(te[X].r,te[now].r,Mid+1,r,id,x); } void que(int X,int l,int r,int x){ if (Mid==x) {anw=te[X].x; return;} if (x<Mid) que(te[X].l,l,Mid-1,x); else que(te[X].r,Mid+1,r,x); } signed main () { freopen("string.in","r",stdin); freopen("string.out","w",stdout); read(n); read(m); read(op); for (int i=1;i<=n;i++) { read(fr); read(at); if (op) fr^=lastans,at^=lastans; fp[i]=at; f[i][0]=fr; l=len[i]=len[fr]+1; for (int j=1;j<=20;j++) f[i][j]=f[f[i][j-1]][j-1]; que(rot[fr],1,m,at); writeln(lastans=(l-len[anw])); opt=i; Le=len[anw]+1; for (int j=20;~j;j--) if (len[f[opt][j]]>=Le) opt=f[opt][j]; ins(rot[anw],rot[i]=++tot,1,m,fp[opt],opt); } return 0; }

BZOJ 十連測 可持久化字符串