├── .gitignore ├── Algorithm ├── DSU_On_Tree(General).cpp ├── Geometry.cpp ├── MCMF.cpp ├── Max_Flow.cpp └── Multiply_LCA.cpp ├── Data_Structure ├── 01Trie.cpp ├── AFL(Cactus).cpp ├── Cartesian_Tree.cpp ├── Chairman_Tree.cpp ├── KD_Tree.cpp ├── Persistent_LiChao_SegmentTree.cpp ├── Rollback_UFS.cpp ├── Segment_Tree(Dynamic_Memory).cpp └── Segment_Tree.cpp ├── Graph ├── Dijkstra.cpp ├── Dijkstra_interval_graph.cpp ├── EulorTour.cpp ├── Tarjan(BCC_Edge).cpp ├── Tarjan(BCC_Point).cpp ├── Tarjan(SCC).cpp └── Tree │ ├── Edge-Divide&Conquer.cpp │ ├── Heavy_Light_Decomposition.cpp │ ├── Point-Divide&Conquer.cpp │ └── Virtual_Tree.cpp ├── Math ├── BerlekampMassey.cpp ├── CRT.cpp ├── FFT.cpp ├── FWT.cpp ├── Gauss.cpp ├── Linear_Basis.cpp ├── Matrix.cpp ├── Mobius.cpp └── linear_sieve.cpp ├── Others ├── Header.cpp └── formula.txt ├── README.md └── String ├── Automaton ├── Aho-Corasick_Automaton.cpp ├── C-SAM(CDAWG).cpp ├── Count_Substrings_In_Segment.cpp ├── Generalized_Palindrome_Automaton.cpp ├── Generalized_Suffix_Automaton.cpp ├── Palindromic_Automaton.cpp └── Suffix_Automaton.cpp ├── Dictionary_of_Basic_Factors.cpp ├── EX_KMP.cpp ├── Hash.cpp ├── KMP.cpp ├── Manacher.cpp ├── Palindrome_Series.cpp ├── Suffix_Array.cpp ├── Trie-Graph(SegmentTree).cpp └── Trie-Graph.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe -------------------------------------------------------------------------------- /Algorithm/DSU_On_Tree(General).cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 18-10-8. 2 | // 1-rooted tree 3 | // query vertex with height H in subtree of V 4 | // whether the letter can form a palindrome 5 | #include 6 | using namespace std; 7 | typedef long long ll; 8 | typedef pair pii; 9 | #define rep(i,l,r) for (ll i = l,_ = r;i< _;i++) 10 | #define REP(i,l,r) for (ll i=l,_=r;i<=_;i++) 11 | const int maxn = 5e5+100; 12 | int n,tot,first[maxn],des[maxn],nxt[maxn],m; 13 | vector Q[maxn]; 14 | int cnt[maxn][26],Cnt[maxn]; 15 | int sz[maxn],dep[maxn],wson[maxn]; 16 | bool ans[maxn],big[maxn]; 17 | char s[maxn]; 18 | inline void addEdge(int x,int y){ 19 | tot++;des[tot] = y; 20 | nxt[tot] = first[x]; 21 | first[x] = tot; 22 | } 23 | void get_sz(int node,int depth){ 24 | dep[node] = depth;sz[node] = 1; 25 | for (int t = first[node];t;t=nxt[t]){ 26 | int v = des[t]; 27 | get_sz(v,depth+1); 28 | sz[node] += sz[v]; 29 | if (sz[v] > sz[wson[node]])wson[node] = v; 30 | } 31 | } 32 | void add(int node,int sign){ 33 | Cnt[dep[node]] -= cnt[dep[node]][s[node]-'a']; 34 | cnt[dep[node]][s[node]-'a'] ^=1; 35 | Cnt[dep[node]] += cnt[dep[node]][s[node]-'a']; 36 | for (int t = first[node];t;t=nxt[t]){ 37 | int v = des[t]; 38 | if (big[v])continue; 39 | add(v,sign); 40 | } 41 | } 42 | void dfs(int node,bool keep){ 43 | for (int t = first[node];t;t=nxt[t]){ 44 | int v = des[t]; 45 | if (v == wson[node])continue; 46 | dfs(v,0); 47 | } 48 | if (wson[node]){ 49 | big[wson[node]]=1; 50 | dfs(wson[node],1); 51 | } 52 | add(node,1); 53 | for (auto q:Q[node]){ 54 | ans[q.second] = Cnt[q.first] <=1; 55 | } 56 | if (wson[node])big[wson[node]] = 0; 57 | if (!keep)add(node,-1); 58 | } 59 | int main(){ 60 | scanf("%d%d",&n,&m); 61 | REP(i,2,n){ 62 | int p; 63 | scanf("%d",&p); 64 | addEdge(p,i); 65 | } 66 | scanf("%s",s+1); 67 | rep(i,0,m){ 68 | int v,h; 69 | scanf("%d%d",&v,&h); 70 | Q[v].push_back({h,i}); 71 | } 72 | get_sz(1,1);dfs(1,0); 73 | rep(i,0,m)printf("%s\n",ans[i]?"Yes":"No"); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /Algorithm/Geometry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int maxn = 10000 + 50; 4 | template 5 | struct point{ 6 | type x,y; 7 | point(){}; 8 | point(type x_,type y_):x(x_),y(y_){} 9 | point operator +(const point &p)const {return point(x + p.x,y + p.y);} 10 | point operator -(const point &p)const {return point(x - p.x,y - p.y);} 11 | //a related to b 12 | //clockwise : positive 13 | //anti-clockwise : negative 14 | //share a line : zero 15 | type cross(const point &p)const {return x * p.y - y * p.x;} 16 | type dot(const point &p)const {return x * p.x + y * p.y;} 17 | type cross(const point &a,const point &b)const {return (a - *this).cross(b - *this);} 18 | type dot(const point &a,const point &b)const {return (a - *this).dot(b - *this);} 19 | type sqrLen()const{return this->dot(*this);} 20 | type sqrDis(const point &p)const {return (p - *this).sqrLen();} 21 | }; 22 | typedef point pt; 23 | namespace Geometry{ 24 | const double PI = acos(-1.0); 25 | //res[0]: left most and bottom most 26 | //anti-clockwise 27 | //no three points share one line 28 | //WARN: this function modifies points 29 | vector Convex_Hull(vector &points){ 30 | vector res(0); 31 | assert(points.size() >= 3); 32 | int idx = 0; 33 | for (int i=1;i 0; 42 | return points[0].sqrDis(x) < points[0].sqrDis(y); 43 | }); 44 | res.push_back(points[0]); 45 | res.push_back(points[1]); 46 | for (int i=2;i= 2){ 49 | double cro = res[res.size()-2].cross(now,res.back()); 50 | auto p = res[res.size()-2]; 51 | auto pp = res.back(); 52 | if (cro >= 0)res.pop_back(); 53 | else break; 54 | } 55 | res.push_back(now); 56 | } 57 | return res; 58 | } 59 | //calc the Minkowski Sum of two Convex Hull 60 | vector Minkowski(const vector &ch1,const vector &ch2){ 61 | assert(ch1.size() >= 3); 62 | assert(ch2.size() >= 3); 63 | stack vec1; 64 | stack vec2; 65 | for (int i = ch1.size() - 1;i >=0;i--){ 66 | vec1.push(ch1[(i+1)%ch1.size()] - ch1[i]); 67 | } 68 | for (int i = ch2.size() - 1;i >= 0;i--){ 69 | vec2.push(ch2[(i+1)%ch2.size()] - ch2[i]); 70 | } 71 | vector res(0); 72 | res.push_back(ch1.front() + ch2.front()); 73 | while (!vec1.empty() && !vec2.empty()){ 74 | auto v1 = vec1.top(); 75 | auto v2 = vec2.top(); 76 | long long cro = v1.cross(v2); 77 | if (cro > 0){ 78 | res.push_back(res.back() + v1); 79 | vec1.pop(); 80 | }else{ 81 | res.push_back(res.back() + v2); 82 | vec2.pop(); 83 | } 84 | } 85 | while (!vec1.empty())res.push_back(res.back() + vec1.top()),vec1.pop(); 86 | while (!vec2.empty())res.push_back(res.back() + vec2.top()),vec2.pop(); 87 | return Convex_Hull(res); 88 | } 89 | //logn 90 | //wether point in or on convex hull 91 | bool within(pt p,const vector &ch){ 92 | assert(ch.size() >= 3); 93 | auto base = ch.front(); 94 | if (base.cross(p,ch[1]) > 0 || base.cross(p,ch.back()) < 0)return false; 95 | if (base.cross(p,ch[1]) == 0 && (p - base).sqrLen() <= (ch[1] - base).sqrLen())return true; 96 | auto cmp = [&](const pt x,const pt y){ 97 | long long cro = base.cross(x,y); 98 | return cro>0; 99 | }; 100 | int i = lower_bound(ch.begin(),ch.end(),p,cmp) - ch.begin() - 1; 101 | int j = i+1; 102 | assert(j < ch.size()); 103 | return ch[i].cross(ch[j],p) >= 0; 104 | } 105 | }; 106 | 107 | -------------------------------------------------------------------------------- /Algorithm/MCMF.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Created by calabash_boy on 19-10-5. 3 | #include 4 | using namespace std; 5 | const int maxn = 3 * 250 + 100; 6 | const int maxm = 2 * 250 * 250 + 100; 7 | const int inf = 10000; 8 | const int INF = 0x3f3f3f3f; 9 | struct MCMF{ 10 | int ss,tt,dis[maxn],pre[maxn]; 11 | int first[maxn],from[maxm*2],des[maxm*2],nxt[maxm*2],cost[maxm*2],flow[maxm*2],tot; 12 | bool in[maxn]; 13 | MCMF(){ 14 | clear(); 15 | } 16 | void clear(){ 17 | tot =-1; 18 | memset(first,-1,sizeof first); 19 | } 20 | // 21 | void init(vector > E){ 22 | for (auto edge : E){ 23 | int u,v,f,c; 24 | tie(u,v,f,c) = edge; 25 | addEdge(u, v, f, c); 26 | } 27 | } 28 | void __addE(int x,int y,int f,int c){ 29 | tot++; 30 | from[tot] =x;des[tot] =y; 31 | flow[tot] =f;cost[tot] =c; 32 | nxt[tot] = first[x];first[x] = tot; 33 | } 34 | inline void addEdge(int x,int y,int f,int c){ 35 | __addE(x,y,f,c);__addE(y,x,0,-c); 36 | } 37 | bool spfa(){ 38 | memset(in,0,sizeof in); 39 | for (int i=0;i Q;Q.push(ss); 43 | while (!Q.empty()){ 44 | int q = Q.front(); 45 | Q.pop();in[q] = 0; 46 | for (int t = first[q];t!=-1;t = nxt[t]){ 47 | int v=des[t],len=cost[t],cx=flow[t]; 48 | if (cx&&dis[v]>dis[q]+len){ 49 | dis[v] = dis[q]+len; 50 | pre[v] = t; 51 | if (!in[v]){ 52 | Q.push(v);in[v] = 1; 53 | } 54 | } 55 | } 56 | } 57 | // min cost max flow 58 | //return pre[tt] != -1; 59 | 60 | // min cost. flow needn't be max. 61 | return pre[tt]!=-1 && dis[tt] < 0; 62 | } 63 | // 64 | pair run(int s, int t){ 65 | ss =s;tt=t; 66 | int totflow =0,totcost =0,nowflow =0,nowcost =0; 67 | while (spfa()){ 68 | nowcost =0;nowflow = INF; 69 | int now =pre[tt]; 70 | while (now!=-1){ 71 | nowflow = min(nowflow,flow[now]); 72 | now = pre[from[now]]; 73 | } 74 | now = pre[tt]; 75 | while (now!=-1){ 76 | flow[now] -= nowflow; 77 | flow[now^1] += nowflow; 78 | nowcost +=cost[now]; 79 | now = pre[from[now]]; 80 | } 81 | nowcost*=nowflow; 82 | totflow +=nowflow; 83 | totcost +=nowcost; 84 | } 85 | return make_pair(totflow,totcost); 86 | } 87 | // special 88 | void output(int cost); 89 | }mcmf; 90 | int n,m; 91 | int a[maxn]; 92 | int id[maxn]; 93 | int argvalue[maxn]; 94 | vector ans; 95 | void copy(int argid,int val){ 96 | stringstream stm; 97 | stm<<(char)('a' + argid - 1)<<"="<>n>>m; 143 | for (int i=1;i<=n;i++){ 144 | cin>>a[i]; 145 | } 146 | vector > E(0); 147 | int SS = 2 * n + 1; 148 | int S = 2 * n + 2; 149 | int T = 2 * n + 3; 150 | E.push_back(make_tuple(SS,S,m,0)); 151 | for (int i=1;i<=n;i++){ 152 | int A = 2 * i - 1; 153 | int B = 2 * i; 154 | E.push_back(make_tuple(A,B,1,-inf)); 155 | E.push_back(make_tuple(S,A,1,__builtin_popcount(a[i]))); 156 | E.push_back(make_tuple(B,T,1,0)); 157 | for (int j=i+1;j<=n;j++){ 158 | int AA = 2 * j - 1; 159 | int BB = 2 * j; 160 | if (a[i] == a[j]){ 161 | E.push_back(make_tuple(B,AA,1,0)); 162 | }else{ 163 | E.push_back(make_tuple(B,AA,1,__builtin_popcount(a[j]))); 164 | } 165 | } 166 | } 167 | mcmf.init(E); 168 | pair ans = mcmf.run(SS, T); 169 | //cerr< 3 | using namespace std; 4 | typedef long long ll; 5 | const int maxn = 11000; 6 | const int maxm = 110000; 7 | const int INF = 0x3f3f3f3f; 8 | struct Max_Flow{ 9 | int first[maxn],nxt[maxm*2],des[maxm*2],c[maxm*2],tot; 10 | int dep[maxn];int ss,tt; 11 | Max_Flow(){ clear(); } 12 | void clear(){ 13 | memset(first,-1,sizeof first);tot =-1; 14 | } 15 | inline void addEdge(int u,int v,int w){ 16 | tot++; 17 | des[tot] = v;c[tot] =w; 18 | nxt[tot] = first[u];first[u] = tot; 19 | } 20 | bool bfs(){ 21 | memset(dep,-1,sizeof dep); 22 | dep[ss] =0; 23 | queue Q;Q.push(ss); 24 | while (!Q.empty()){ 25 | int q = Q.front();Q.pop(); 26 | for (int t = first[q];t!=-1;t= nxt[t]){ 27 | int v = des[t],cx = c[t]; 28 | if (dep[v]==-1&&cx){ 29 | dep[v] = dep[q]+1; 30 | Q.push(v); 31 | } 32 | } 33 | } 34 | return dep[tt]!=-1; 35 | } 36 | int dfs(int node,int now){ 37 | if (node==tt)return now; 38 | int res =0; 39 | for (int t = first[node];t!=-1&&res 51 | void init(vector > Edge){ 52 | for (auto tp : Edge){ 53 | int u,v,w;tie(u,v,w) = tp; 54 | addEdge(u,v,w);addEdge(v,u,0); 55 | } 56 | } 57 | // s->t max_flow 58 | ll max_flow(int s,int t){ 59 | ss = s;tt = t; 60 | ll res =0,del =0; 61 | while (bfs()){while (del = dfs(ss,INF)){res += del;}} 62 | return res; 63 | } 64 | }net; 65 | int n,m,s,t; 66 | vector > E; 67 | int main(){ 68 | scanf("%d%d%d%d",&n,&m,&s,&t); 69 | for (int i=0;i 3 | using namespace std; 4 | const int maxn = 5e5+100; 5 | int first[maxn],des[maxn*2],nxt[maxn*2],tot; 6 | int n,m,s; 7 | inline int addEdge(int x,int y){ 8 | tot++;des[tot] = y; 9 | nxt[tot] = first[x]; 10 | first[x] = tot; 11 | } 12 | namespace Multiply_LCA{ 13 | int fa[maxn][20],dep[maxn]; 14 | void dfs(int u,int father){ 15 | fa[u][0] = father; 16 | dep[u] = dep[father]+1; 17 | for (int i=1;i<20&&fa[u][i-1];i++){ 18 | fa[u][i] = fa[fa[u][i-1]][i-1]; 19 | } 20 | for (int t=first[u];t;t=nxt[t]){ 21 | int v = des[t]; 22 | if (v==father)continue; 23 | dfs(v,u); 24 | } 25 | } 26 | int lca(int x,int y){ 27 | if (dep[x]=0;i--){ 29 | if (dep[fa[x][i]]>=dep[y]){ 30 | x = fa[x][i]; 31 | } 32 | } 33 | if (x==y)return x; 34 | for (int i=19;i>=0;i--){ 35 | if (fa[x][i]!=fa[y][i]){ 36 | x = fa[x][i]; 37 | y = fa[y][i]; 38 | } 39 | } 40 | return fa[y][0]; 41 | } 42 | }; 43 | int main(){ 44 | scanf("%d%d%d",&n,&m,&s); 45 | for (int i=1;i 4 | using namespace std; 5 | const int MAX = 1e6+100; 6 | int bas[35],n,Cas; 7 | const int INF = 2147483645; 8 | struct Trie{ 9 | int nxt[MAX<<2][2],l[MAX<<2]; 10 | int cnt,ansl,ansr,ansv; 11 | void init(){ 12 | cnt =ansv = 0; 13 | memset(nxt[0],0,sizeof (nxt[0])); 14 | memset(l,0x3f3f3f3f,sizeof(l)); 15 | } 16 | int create(){ 17 | cnt++; 18 | memset(nxt[cnt],0,sizeof (nxt[cnt])); 19 | return cnt; 20 | } 21 | void insert(int id,int x){ 22 | int y = 0; 23 | for (int i=30;i>=0;i--){ 24 | int t = x&bas[i]; 25 | t>>=i; 26 | if (!nxt[y][t])nxt[y][t] = create(); 27 | y = nxt[y][t]; 28 | } 29 | l[y] = min(l[y],id); 30 | } 31 | void query(int id,int x){ 32 | int y=0; int res =0; 33 | for (int i=30;i>=0;i--){ 34 | int t = x&bas[i]; 35 | t>>=i; 36 | if (nxt[y][!t]){ 37 | y =nxt[y][!t]; 38 | res+=bas[i]; 39 | }else{ 40 | y = nxt[y][t]; 41 | } 42 | } 43 | if (res==ansv){ 44 | if (l[y]ansv){ 48 | ansv = res; 49 | ansl = l[y]; 50 | ansr = id; 51 | } 52 | } 53 | }trie; 54 | int main(){ 55 | bas[0] = 1; 56 | for (int i1=1;i1<=30;i1++)bas[i1] = bas[i1-1]<<1; 57 | scanf("%d",&Cas); 58 | for (int i=1;i<=Cas;i++){ 59 | trie.init(); trie.insert(0,0); 60 | scanf("%d",&n); 61 | int sum=0; 62 | for (int j=1;j<=n;j++){ 63 | int ai; 64 | scanf("%d",&ai); sum^=ai; 65 | trie.query(j,sum); trie.insert(j,sum); 66 | } 67 | printf("Case #%d:\n%d %d\n", i, trie.ansl + 1, trie.ansr); 68 | } 69 | return 0; 70 | } -------------------------------------------------------------------------------- /Data_Structure/AFL(Cactus).cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 18-9-14. 2 | // circle-square-tree Maximum independent set 3 | #include 4 | using namespace std; 5 | const int maxn = 1e5+100; 6 | vector E1[maxn],ET[maxn]; 7 | int m,n,N,fa[maxn],dp[maxn][2]; 8 | int len[maxn],dfn[maxn],dfs_clock; 9 | bool inCircle[maxn]; 10 | int dp2[maxn][2]; 11 | inline void addEdge1(int x,int y){ 12 | E1[x].push_back(y); 13 | } 14 | inline void addEdgeT(int x,int y){ 15 | ET[x].push_back(y); 16 | } 17 | void input(){ 18 | cin>>n>>m;N =n; 19 | for (int i=0;i>u>>v; 21 | addEdge1(u,v);addEdge1(v,u); 22 | } 23 | } 24 | void tarjan(int u){ 25 | dfn[u] = ++dfs_clock; 26 | for (int i=0;i=0;i--){ 67 | dp2[i][0] = max(dp2[i+1][0],dp2[i+1][1])+dp[ET[x][i]][0]; 68 | dp2[i][1] = dp2[i+1][0]+dp[ET[x][i]][1]; 69 | } 70 | dp[x][1] = max(dp[x][1],max(dp2[0][0],dp2[0][1])); 71 | } 72 | void dfs(int u){ 73 | dp[u][0]=0;dp[u][1]=1; 74 | if (u>N)dp[u][0]=0; 75 | for (int i=0;iN)work(u); 84 | } 85 | int main(){ 86 | input(); 87 | tarjan(1); 88 | dfs(1); 89 | cout< 4 | using namespace std; 5 | #define OPENSTACK 6 | const int maxn = 1e6+100; 7 | const int mod = 1e9+7; 8 | typedef long long LL; 9 | int stk[maxn],top,sz[maxn]; 10 | int l[maxn],r[maxn],rt,n; 11 | pair a[maxn]; 12 | LL inv[maxn],fac[maxn],inv_fac[maxn]; 13 | bool vis[maxn]; 14 | /* l 左儿子 r 右儿子 rt根*/ 15 | void build(){ 16 | top=0; 17 | for (int i=1;i<=n;i++) l[i]=r[i]=vis[i] =0; 18 | for (int i=1;i<=n;i++){ 19 | int k = top; 20 | while (k&&a[i]>=1; 38 | x = x*x%mod; 39 | } 40 | return res; 41 | } 42 | inline LL C(int n,int m){ 43 | return fac[n]*inv_fac[m]%mod*inv_fac[n-m]%mod; 44 | } 45 | int dfs(int u){ 46 | sz[u]=1;int ans =1; 47 | if (l[u])ans=1LL*ans*dfs(l[u])%mod; 48 | if (r[u])ans = 1LL*ans*dfs(r[u])%mod; 49 | sz[u]+=sz[l[u]]+sz[r[u]]; 50 | return 1LL*ans*C(sz[u]-1,sz[l[u]])%mod; 51 | } 52 | void Main(){ 53 | inv[1]=fac[1]=fac[0]=1; 54 | for (int i=2;i=0;i--){ 57 | inv_fac[i] = inv_fac[i+1]*(i+1)%mod; 58 | } 59 | int T;scanf("%d",&T); 60 | while (T--) { 61 | scanf("%d", &n); 62 | for (int i = 1; i <= n; i++) { 63 | int x;scanf("%d", &x); 64 | a[i] = {-x, i}; 65 | } 66 | build(); 67 | printf("%d\n", inv[2] * n % mod * power(fac[n], mod - 2) % mod * dfs(rt) % mod); 68 | } 69 | } 70 | int main(){ 71 | #ifdef OPENSTACK 72 | int size = 70 << 20; // 256MB 73 | char *p = (char*)malloc(size) + size; 74 | #if (defined _WIN64) or (defined __unix) 75 | __asm__("movq %0, %%rsp\n" :: "r"(p)); 76 | #else 77 | __asm__("movl %0, %%esp\n" :: "r"(p)); 78 | #endif 79 | #endif 80 | Main(); 81 | #ifdef OPENSTACK 82 | exit(0); 83 | #else 84 | return 0; 85 | #endif 86 | } -------------------------------------------------------------------------------- /Data_Structure/Chairman_Tree.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 18-7-7. 2 | // query_kth_element 3 | #include 4 | using namespace std; 5 | const int maxn=1e5+100; 6 | int a[maxn];int rk[maxn];int pos[maxn]; 7 | int root[maxn];int cnt,m,n,T; 8 | struct Chairman_Tree{ 9 | struct Node{int L,R,val;}tree[maxn*500]; 10 | void init(){ 11 | memset(root,0,sizeof root); 12 | cnt =0; 13 | } 14 | /* 建T0空树 */ 15 | int buildT0(int l, int r){ 16 | int k = cnt++; 17 | tree[k].val =0; 18 | if (l==r) return k; 19 | int mid = l+r >>1; 20 | tree[k].L = buildT0(l, mid);tree[k].R = buildT0(mid + 1, r); 21 | return k; 22 | } 23 | /* 上一个版本节点P,【ppos】+=del 返回新版本节点*/ 24 | int update (int P,int l,int r,int ppos,int del){ 25 | int k = cnt++; 26 | tree[k].val = tree[P].val +del; 27 | if (l==r) return k; 28 | int mid = l+r >>1; 29 | if (ppos<=mid){ 30 | tree[k].L = update(tree[P].L,l,mid,ppos,del); 31 | tree[k].R = tree[P].R; 32 | }else{ 33 | tree[k].L = tree[P].L; 34 | tree[k].R = update(tree[P].R,mid+1,r,ppos,del); 35 | } 36 | return k; 37 | } 38 | int query_kth(int lt,int rt,int l,int r,int k){ 39 | if (l==r) return a[rk[l]]; 40 | int mid = l+r >>1; 41 | if (tree[tree[rt].L].val-tree[tree[lt].L].val>=k) return query_kth(tree[lt].L,tree[rt].L,l,mid,k); 42 | else return query_kth(tree[lt].R,tree[rt].R,mid+1,r,k+tree[tree[lt].L].val-tree[tree[rt].L].val); 43 | } 44 | }tree; 45 | bool cmp(int x,int y){return a[x] 3 | using namespace std; 4 | typedef long long LL; 5 | const int maxn = 2e5+100; 6 | const LL INF = 0x3f3f3f3f3f3f3f3fLL; 7 | int m,n; 8 | const int demension = 2; 9 | struct Hotel{ 10 | int pos[demension],id,c; 11 | }hotel[maxn],kdtree[maxn]; 12 | double var[demension]; 13 | int split [maxn];int cmpDem; 14 | bool cmp(const Hotel &a,const Hotel &b){ 15 | return a.pos[cmpDem]=r)return; 19 | int mid = l+r >>1; 20 | for (int i=0;imaxVar){ 34 | maxVar = var[i]; 35 | split[mid] =i; 36 | } 37 | } 38 | cmpDem = split[mid]; 39 | nth_element(hotel+l,hotel+mid,hotel+r+1,cmp); 40 | build (l,mid-1);build (mid+1,r); 41 | } 42 | int ansIndex; 43 | LL ansDis; 44 | void query(int l,int r,const Hotel& x){ 45 | if (l>r)return ; 46 | int mid = l+r >>1;LL dis =0; 47 | for (int i=0;iradius){query(mid+1,r,x);} 63 | }else{ 64 | query(mid+1,r,x); 65 | if (ansDis>radius){query(l,mid-1,x);} 66 | } 67 | } 68 | int T; 69 | void input(){ 70 | scanf("%d%d",&n,&m); 71 | for (int i=0;i 3 | using namespace std; 4 | #define int ll 5 | typedef long long ll; 6 | const int inf = 1e9 + 5; 7 | const int maxn = 80000 + 50; 8 | const int maxq = 160000 + 50; 9 | struct Node{ 10 | int lson,rson,k,b; 11 | //y = k * x + b 12 | void init(){ 13 | lson = rson = 0; 14 | k = b = inf; 15 | } 16 | }nodes[maxn * 300]; 17 | int node_cnt = 0; 18 | int root[maxn]; 19 | int update(int x,int l,int r,int L,int R,int k,int b){ 20 | int now = node_cnt ++; 21 | nodes[now] = nodes[x]; 22 | int mid = l + r >> 1; 23 | if (l == L && r == R){ 24 | if (k * mid + b < nodes[now].k * mid + nodes[now].b){ 25 | swap(k,nodes[now].k); 26 | swap(b,nodes[now].b); 27 | } 28 | if (l == r)return now; 29 | if (k * l + b < nodes[now].k * l + nodes[now].b){ 30 | nodes[now].lson = update(nodes[x].lson,l,mid,l,mid,k,b); 31 | } 32 | if (k * r + b < nodes[now].k * r + nodes[now].b){ 33 | nodes[now].rson = update(nodes[x].rson,mid+1,r,mid+1,r,k,b); 34 | } 35 | return now; 36 | } 37 | if (L <= mid)nodes[now].lson = update(nodes[x].lson,l,mid,L,min(mid,R),k,b); 38 | if (mid + 1 <= R)nodes[now].rson = update(nodes[x].rson,mid+1,r,max(mid+1,L),R,k,b); 39 | return now; 40 | } 41 | int n,q; 42 | int a[maxn], b[maxn], c[maxn]; 43 | vector E[maxn]; 44 | void dfs(int u,int fa){ 45 | root[u] = update(root[fa],0,inf,0,c[u],b[u],a[u]); 46 | for (int v : E[u]){ 47 | if (v == fa)continue; 48 | dfs(v,u); 49 | } 50 | } 51 | ll query(int x,int l,int r,int pos){ 52 | int res = nodes[x].k * pos + nodes[x].b; 53 | //cerr<> 1; 56 | if (pos <= mid && nodes[x].lson )res = min(res,query(nodes[x].lson,l,mid,pos)); 57 | else if (pos > mid &&nodes[x].rson ) res = min(res,query(nodes[x].rson,mid+1,r,pos)); 58 | return res; 59 | } 60 | signed main(){ 61 | scanf("%lld%lld",&n,&q); 62 | for (int i=1;i<=n;i++)scanf("%lld",a+i); 63 | for (int i=1;i<=n;i++)scanf("%lld",b+i); 64 | for (int i=1;i<=n;i++)scanf("%lld",c+i); 65 | for (int i=1;i 3 | using namespace std; 4 | const int maxn = 1e5 + 20; 5 | struct UFS{ 6 | int fa[maxn]; 7 | int sz[maxn]; 8 | int len[maxn]; 9 | stack > stk; 10 | void init(){ 11 | for (int i=1;i find(int x){ 21 | if (fa[x] == x)return make_pair(x,0); 22 | else{ 23 | pair ret = find(fa[x]); 24 | ret.second ^= len[x]; 25 | return ret; 26 | } 27 | } 28 | // 0 fail 29 | // 1 succ but not update 30 | // 2 succ and update 31 | int merge(int x,int y){ 32 | int fx,lenx; 33 | int fy,leny; 34 | tie(fx,lenx) = find(x); 35 | tie(fy,leny) = find(y); 36 | if (fx == fy){ 37 | return lenx ^ leny; 38 | } 39 | if (sz[fx] > sz[fy]){ 40 | swap(lenx,leny); 41 | swap(x,y); 42 | swap(fx,fy); 43 | } 44 | stk.push(make_pair(&sz[fy],sz[fy])); 45 | stk.push(make_pair(&fa[fx],fa[fx])); 46 | fa[fx] = fy; 47 | sz[fy] += sz[fx]; 48 | if (lenx == leny){ 49 | len[fx] = 1; 50 | }else{ 51 | len[fx] = 0; 52 | } 53 | return 2; 54 | } 55 | void rollback(){ 56 | for (int i=0;i<2;i++){ 57 | int * tar; 58 | int val; 59 | tie(tar,val) = stk.top(); 60 | stk.pop(); 61 | (*tar) = val; 62 | } 63 | 64 | } 65 | }ufs; 66 | const char* YES = "YES"; 67 | const char* NO = "NO"; 68 | bool ans[maxn]; 69 | struct SegmentTree{ 70 | vector > edges[maxn*4]; 71 | void put(int x,int l,int r,int L,int R,pair e){ 72 | if (l > R || L > r)return; 73 | if (L <= l && r <= R){ 74 | edges[x].push_back(e); 75 | return; 76 | } 77 | int mid = l + r >> 1; 78 | put(x<<1,l,mid,L,R,e); 79 | put(x<<1|1,mid+1,r,L,R,e); 80 | } 81 | void dfs(int x,int l,int r){ 82 | int succ = true; 83 | int cnt = 0; 84 | for (auto e : edges[x]){ 85 | int x,y; 86 | tie(x,y) = e; 87 | int ret = ufs.merge(x, y); 88 | succ &= ret!= 0; 89 | if (!succ){ 90 | for (int i=0;i> 1; 103 | dfs(x<<1,l,mid); 104 | dfs(x<<1|1,mid+1,r); 105 | for (int i=0;i"<> 1; 117 | debug(x<<1,l,mid); 118 | debug(x<<1|1,mid+1,r); 119 | } 120 | }segtree; 121 | map,vector > mp; 122 | int main(){ 123 | int n,q; 124 | cin>>n>>q; 125 | for (int i=1;i<=q;i++){ 126 | int u,v; 127 | cin>>u>>v; 128 | if (u > v)swap(u,v); 129 | mp[make_pair(u,v)].push_back(i); 130 | } 131 | for (auto pr : mp){ 132 | vector & ts = pr.second; 133 | if (ts.size() & 1){ 134 | ts.push_back(q+1); 135 | } 136 | for (int i=0;i 8 | using namespace std; 9 | const int maxn = 1e5+100; 10 | typedef long long ll; 11 | struct Node{ int L,R,val; }tree[maxn*200]; 12 | int cnt; 13 | struct Segment_Tree{ 14 | int root = 0; 15 | int newnode(){ 16 | ++cnt; 17 | tree[cnt].val = tree[cnt].L = tree[cnt].R = 0; 18 | return cnt; 19 | } 20 | Segment_Tree(){ root = newnode(); } 21 | void add(int x,int l,int r,int Pos,int delta){ 22 | tree[x].val += delta; 23 | if (l == r)return; 24 | int mid = l+r >>1; 25 | if (Pos <= mid){ 26 | if (tree[x].L == 0){ 27 | tree[x].L = newnode(); 28 | } 29 | add(tree[x].L,l,mid,Pos,delta); 30 | }else{ 31 | if (tree[x].R == 0){ 32 | tree[x].R = newnode(); 33 | } 34 | add(tree[x].R,mid+1,r,Pos,delta); 35 | } 36 | } 37 | int query(int x,int l,int r,int L,int R){ 38 | if (!x)return 0; 39 | if (l>R || L>r)return 0; 40 | if (L <= l && r <= R)return tree[x].val; 41 | int mid = l+r >>1; 42 | return query(tree[x].L,l,mid,L,R) + query(tree[x].R,mid+1,r,L,R); 43 | } 44 | }; 45 | map mp; 46 | map id; 47 | int N; 48 | int main(){ 49 | int n,k; 50 | scanf("%d%d",&n,&k); 51 | vector > a(n); 52 | vector nums; 53 | for (int i=0;i &a,const tuple&b){ 67 | return get<1>(a) > get<1>(b); 68 | }); 69 | ll ans =0; 70 | for (int i=0;i 4 | using namespace std; 5 | const int maxn = 1e5+100; 6 | typedef long long LL; 7 | int a[maxn]; 8 | struct Seg_Tree{ 9 | LL val[maxn*4];LL lazy[maxn*4]; 10 | inline void Up(int x){val[x] = val[x<<1]+val[x<<1|1];} 11 | inline void Down(int x,int l,int mid,int r){ 12 | if (lazy[x]){ 13 | val[x<<1] += 1LL*lazy[x]*(mid-l+1); 14 | val[x<<1|1] += 1LL*lazy[x]*(r-mid); 15 | lazy[x<<1]+= lazy[x]; 16 | lazy[x<<1|1] += lazy[x]; 17 | lazy[x] =0; 18 | } 19 | } 20 | void build (int x,int l,int r){ 21 | lazy[x] =0; 22 | if (l==r){val[x] = a[l];return ;} 23 | int mid = l+r >>1; 24 | build (x<<1,l,mid);build (x<<1|1,mid+1,r); 25 | Up(x); 26 | } 27 | void add(int x,int l,int r,int L,int R,int del){ 28 | if (l>R||r>1; 35 | Down(x,l,mid,r); 36 | add(x<<1,l,mid,L,R,del);add(x<<1|1,mid+1,r,L,R,del); 37 | Up(x); 38 | } 39 | LL query_Sum(int x,int l,int r,int L,int R){ 40 | if (l>R||r>1; 43 | Down(x,l,mid,r); 44 | return query_Sum(x<<1,l,mid,L,R)+query_Sum(x<<1|1,mid+1,r,L,R); 45 | } 46 | }tree; 47 | char opt[5];int m,n; 48 | int main(){ 49 | scanf("%d%d",&n,&m); 50 | for (int i=1;i<=n;i++){ 51 | scanf("%d",a+i); 52 | } 53 | tree.build(1,1,n); 54 | while (m--){ 55 | int l,r,v; 56 | scanf("%s%d%d",opt,&l,&r); 57 | if (opt[0]=='Q'){ 58 | printf("%I64d\n",tree.query_Sum(1,1,n,l,r)); 59 | }else if (opt[0]=='C'){ 60 | scanf("%d",&v); 61 | tree.add(1,1,n,l,r,v); 62 | } 63 | } 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /Graph/Dijkstra.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 18-11-13. 2 | // remain k bi-edge such that the most points' dis == min_dis 3 | #include 4 | using namespace std; 5 | typedef long long ll; 6 | const ll inf_ll = 0x3f3f3f3f3f3f3f3fll; 7 | const int inf = 0x3f3f3f3f; 8 | const int maxn = 300005; 9 | struct EDGE{int first,second,third;}; 10 | int n,m,k; 11 | namespace Short_Path_Tree{ 12 | vector > Edge[maxn]; 13 | bool used[maxn]; 14 | void add_edge(int x,int y,int w) {Edge[x].push_back({y,w});} 15 | void output(const vector &ans){ 16 | printf("%d\n",(int) ans.size()); 17 | for (int v : ans)printf("%d ",v); 18 | puts("");exit(0); 19 | } 20 | void solve(int K){ 21 | vector ans(0);queue Q; 22 | used[1] = 1;Q.push(1); 23 | while (!Q.empty()){ 24 | if (ans.size()== K)output(ans); 25 | int head = Q.front();Q.pop(); 26 | for (auto pr : Edge[head]){ 27 | if (used[pr.first])continue; 28 | used[pr.first] = 1; 29 | ans.push_back(pr.second); 30 | Q.push(pr.first); 31 | if (ans.size()==K)output(ans); 32 | } 33 | } 34 | output(ans); 35 | } 36 | }; 37 | namespace Dijkstra{ 38 | ll dis[maxn];bool used[maxn]; 39 | vector *Edge;int S,N; 40 | struct Node{ 41 | int x;ll dis; 42 | bool operator < (const Node &other)const{ 43 | return other.dis < dis; 44 | } 45 | }; 46 | void init(vector*Edgee,int n,int st){ 47 | Edge = Edgee;S =st;N = n; 48 | } 49 | void work(){ 50 | memset(dis,inf,sizeof dis); 51 | priority_queue pq; 52 | dis[S] = 0;pq.push({S,0}); 53 | while (!pq.empty()){ 54 | Node head = pq.top();pq.pop(); 55 | if (used[head.x])continue; 56 | used[head.x] = 1; 57 | for (auto pr : Edge[head.x]){ 58 | if (dis[pr.first] > dis[head.x] + pr.second){ 59 | dis[pr.first] = dis[head.x] + pr.second; 60 | pq.push({pr.first,dis[pr.first]}); 61 | } 62 | } 63 | } 64 | } 65 | void extract_spt(){ 66 | for (int u=1;u<=N;u++){ 67 | for (auto pr : Edge[u]){ 68 | if (dis[pr.first] == dis[u] + pr.second){ 69 | Short_Path_Tree::add_edge(u,pr.first,pr.third); 70 | } 71 | } 72 | } 73 | } 74 | }; 75 | vector E[maxn]; 76 | int main(){ 77 | scanf("%d%d%d",&n,&m,&k); 78 | for (int i=1;i<=m;i++){ 79 | int x,y,w;scanf("%d%d%d",&x,&y,&w); 80 | E[x].push_back({y,w,i}); 81 | E[y].push_back({x,w,i}); 82 | } 83 | Dijkstra::init(E,n,1); 84 | Dijkstra::work(); 85 | Dijkstra::extract_spt(); 86 | Short_Path_Tree::solve(k); 87 | return 0; 88 | } -------------------------------------------------------------------------------- /Graph/Dijkstra_interval_graph.cpp: -------------------------------------------------------------------------------- 1 | // CF 786B 2 | #include 3 | using namespace std; 4 | const int maxn = 1e5 + 100; 5 | const int N = 10 * maxn; 6 | typedef long long ll; 7 | namespace Dijkstra{ 8 | vector > E[N]; 9 | ll dis[N]; 10 | bool used[N]; 11 | inline void add_edge(int u,int v,int w){ 12 | E[u].push_back(make_pair(v,w)); 13 | } 14 | void dijkstra(int S, int N){ 15 | priority_queue > pq; 16 | for (int i=1;i<=N;i++){ 17 | dis[i] = 0x3f3f3f3f3f3f3f3fll; 18 | used[i] = 0; 19 | } 20 | dis[S] = 0; 21 | for (int i=1;i<=N;i++){ 22 | pq.push(make_pair(-dis[i],i)); 23 | } 24 | while (!pq.empty()){ 25 | pair head = pq.top();pq.pop(); 26 | int u; ll dist; 27 | tie(dist,u) = head; 28 | dist *= -1; 29 | if (used[u])continue; 30 | used[u] = 1; 31 | for (auto e : E[u]){ 32 | int v,len; 33 | tie(v,len) = e; 34 | if (dis[v] > dist + len){ 35 | dis[v] = dist + len; 36 | pq.push(make_pair(-dis[v],v)); 37 | } 38 | } 39 | } 40 | } 41 | void output(int n){ 42 | for (int i=1;i<=n;i++){ 43 | printf("%lld ",dis[i] == 0x3f3f3f3f3f3f3f3fll ? -1:dis[i]); 44 | } 45 | puts(""); 46 | } 47 | } 48 | int n,q,s; 49 | int cnt; 50 | struct SegmentTree{ 51 | int id[maxn*4]; 52 | void build(int x,int l,int r,bool up){ 53 | id[x] = ++cnt; 54 | if (l == r){ 55 | int u = id[x]; 56 | int v = l; 57 | if (up)swap(u,v); 58 | Dijkstra::add_edge(u, v, 0); 59 | return; 60 | } 61 | int mid = l + r >> 1; 62 | build(x<<1,l,mid,up); 63 | build(x<<1|1,mid+1,r,up); 64 | int u = id[x]; 65 | int v = id[x<<1]; 66 | if (up)swap(u,v); 67 | Dijkstra::add_edge(u, v, 0); 68 | u = id[x]; 69 | v = id[x<<1|1]; 70 | if (up)swap(u,v); 71 | Dijkstra::add_edge(u, v, 0); 72 | } 73 | void add_edge(int x,int l,int r,int L,int R, int T, int w, bool up){ 74 | if (l > R || L > r)return; 75 | if (L <= l && r <= R){ 76 | int u = id[x]; 77 | int v = T; 78 | if (up)swap(u,v); 79 | Dijkstra::add_edge(u, v, w); 80 | return; 81 | } 82 | int mid = l + r >> 1; 83 | add_edge(x<<1, l, mid, L, R, T, w, up); 84 | add_edge(x<<1|1, mid+1, r, L, R, T, w, up); 85 | } 86 | }Down,Up; 87 | int main(){ 88 | scanf("%d%d%d",&n,&q,&s); 89 | cnt = n; 90 | Down.build(1, 1, n, false); 91 | Up.build(1, 1, n, true); 92 | while (q--){ 93 | int t,u,l,r,w; 94 | scanf("%d",&t); 95 | if (t == 1){ 96 | int v; 97 | scanf("%d%d%d",&u,&v, &w); 98 | l = r = v; 99 | t = 2; 100 | }else{ 101 | scanf("%d%d%d%d",&u,&l,&r,&w); 102 | } 103 | if (t == 2){ 104 | // u -> [l,r], len = w 105 | Down.add_edge(1, 1, n, l, r, u, w, true); 106 | }else{ 107 | // [l,r] -> v, len = w 108 | Up.add_edge(1, 1, n, l, r, u, w, false); 109 | } 110 | } 111 | Dijkstra::dijkstra(s, cnt); 112 | Dijkstra::output(n); 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /Graph/EulorTour.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int maxn = 1e5 + 100; 4 | const int maxm = 5e5 + 100; 5 | int n,m; 6 | int d[maxn]; 7 | //<点,到这个点走的边id> 8 | vector > tour; 9 | vector > E[maxn]; 10 | pair edge[maxm]; 11 | bool used[maxm]; 12 | int now[maxn]; 13 | void dfs(int u,int e_id){ 14 | for (; now[u] < E[u].size(); now[u] ++){ 15 | int v,id; 16 | tie(v,id) = E[u][now[u]]; 17 | if (used[id]) continue; 18 | used[id] = 1; 19 | dfs(v,id); 20 | } 21 | tour.push_back(make_pair(u,e_id)); 22 | } 23 | int main(){ 24 | scanf("%d%d",&n,&m); 25 | for (int i=1;i<=m;i++){ 26 | int a,b; 27 | scanf("%d%d",&a,&b); 28 | edge[i] = make_pair(a,b); 29 | E[a].push_back(make_pair(b,i)); 30 | E[b].push_back(make_pair(a,i)); 31 | } 32 | dfs(1,-1); 33 | reverse(tour.begin(), tour.end()); 34 | /* 35 | for (auto pr : tour){ 36 | int u,id; 37 | tie(u,id) = pr; 38 | cerr< 3 | using namespace std; 4 | const int maxn = 1e5+100; 5 | int first[maxn],nxt[maxn*2],from[maxn*2],des[maxn*2],isBrige[maxn*2],tot; 6 | int dfn[maxn],low[maxn],dfs_clock; 7 | int cnt_e[maxn],cnt_n[maxn];int bcc_cnt; 8 | bool ok[maxn];vector ans;int m,n; 9 | inline void addEdge(int x,int y){ 10 | tot++; 11 | des[tot] =y;from[tot] =x; 12 | nxt[tot] = first[x];first[x] = tot; 13 | } 14 | void input(){ 15 | cin>>n>>m; 16 | for (int i=0;i 3 | using namespace std; 4 | const int maxn = 1e5+100; 5 | int first[maxn],des[maxn*2],nxt[maxn*2],tot; 6 | int bcc_cnt,cnt_n[maxn],cnt_e[maxn],bcc_no[maxn]; 7 | int dfn[maxn],low[maxn],dfs_clock; 8 | int st[maxn*2],top;bool ok[maxn]; 9 | vector ans;vector temp; 10 | int m,n; 11 | inline void addEdge(int x,int y){ 12 | tot++;des[tot] = y; 13 | nxt[tot] = first[x];first[x] = tot; 14 | } 15 | void input(){ 16 | cin>>n>>m; 17 | for (int i=0;i=dfn[u]){ 31 | bcc_cnt++;ok[bcc_cnt] = true; 32 | temp.clear(); 33 | while (true){ 34 | int tt = st[--top]; 35 | temp.push_back((tt+1)/2); 36 | if (bcc_no[des[tt]]!=bcc_cnt){ 37 | bcc_no[des[tt]] = bcc_cnt; 38 | cnt_n[bcc_cnt]++; 39 | }else{ 40 | ok[bcc_cnt] = false; 41 | } 42 | cnt_e[bcc_cnt]++; 43 | if (tt==t)break; 44 | } 45 | if (ok[bcc_cnt]&&temp.size()>1){ 46 | for (int i=0;i 2 | using namespace std; 3 | const int maxn = 1e5+100; 4 | int m,n,h;int t[maxn]; 5 | int first[maxn*2],nxt[maxn*2],des[maxn*2],tot; 6 | int dfn[maxn],low[maxn],dft;bool d[maxn]; 7 | int flag[maxn],cnt[maxn],scc;stack stk; 8 | bool in[maxn]; 9 | inline void add(int x,int y){ 10 | tot++;des[tot] =y; 11 | nxt[tot] = first[x];first[x] =tot; 12 | } 13 | void tar(int node){ 14 | dfn[node] = low[node] = ++dft; 15 | in[node] = 1;stk.push(node); 16 | for (int t = first[node];t;t=nxt[t]){ 17 | int v = des[t]; 18 | if (!dfn[v]){ 19 | tar(v); 20 | low[node] = min(low[node],low[v]); 21 | }else if (in[v]){ 22 | low[node] = min(low[node],dfn[v]); 23 | } 24 | } 25 | if (dfn[node]==low[node]){ 26 | scc++; 27 | while (true){ 28 | int temp = stk.top(); 29 | flag[temp]=scc; 30 | in[temp] = 0; 31 | cnt[scc]++;stk.pop(); 32 | if (temp==node)break; 33 | } 34 | } 35 | } 36 | int main(){ 37 | scanf("%d%d%d",&n,&m,&h); 38 | for (int i=1;i<=n;i++){scanf("%d",t+i);} 39 | for (int i=0;i 6 | using namespace std; 7 | const int maxn = 2e5 + 100; 8 | char s[maxn],t[maxn];int n,K1,K2; 9 | struct Suffix_Automaton{ 10 | int nxt[maxn*2][26],fa[maxn*2],l[maxn*2]; 11 | int last,cnt; 12 | Suffix_Automaton(){ clear(); } 13 | void clear(){ 14 | last =cnt=1;fa[1]=l[1]=0; 15 | memset(nxt[1],0,sizeof nxt[1]); 16 | } 17 | void init(char *s){ 18 | while (*s){add(*s-'a');s++;} 19 | } 20 | void add(int c){ 21 | int p = last, np = ++cnt; 22 | memset(nxt[cnt],0,sizeof nxt[cnt]); 23 | l[np] = l[p]+1;last = np; 24 | while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p]; 25 | if (!p)fa[np]=1; 26 | else{ 27 | int q = nxt[p][c]; 28 | if (l[q]==l[p]+1)fa[np] =q; 29 | else{ 30 | int nq = ++ cnt; 31 | l[nq] = l[p]+1; 32 | memcpy(nxt[nq],nxt[q],sizeof (nxt[q])); 33 | fa[nq] =fa[q];fa[np] = fa[q] =nq; 34 | while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p]; 35 | } 36 | } 37 | } 38 | void extract(vector * E,char *s,int n,int *id,int *dep,int K){ 39 | int temp = 1; 40 | for (int i=0;i EE1[maxn * 2],E2[maxn*2]; 52 | vector > E1[maxn*4]; 53 | int idd1[maxn * 2],id1[maxn*4]; 54 | int depp1[maxn * 2],dep1[maxn*4]; 55 | int id2[maxn* 2],dep2[maxn*2]; 56 | bool can_use[maxn*4]; 57 | int edge_cnt = 0; 58 | int cnt, st[maxn * 2][20], depth[maxn * 2]; 59 | int pos2[maxn*2],pos1[maxn*4]; 60 | int dfs_clock,l[maxn*2],r[maxn*2]; 61 | void dfs2(int u,int fa){ 62 | l[u] = ++dfs_clock; 63 | st[u][0] = fa; 64 | depth[u] = depth[fa] + 1; 65 | for (int i=1;i<20 && st[u][i-1];i++){ 66 | st[u][i] = st[st[u][i-1]][i-1]; 67 | } 68 | for (auto v : E2[u]){ 69 | if (v == fa)continue; 70 | dfs2(v,u); 71 | } 72 | r[u] = dfs_clock; 73 | } 74 | int get_lca(int u,int v){ 75 | if (depth[u] < depth[v])swap(u,v); 76 | for (int i=19;i>=0;i--){ 77 | if (depth[st[u][i]] >= depth[v])u = st[u][i]; 78 | } 79 | if (u == v)return u; 80 | for (int i=19;i>=0;i--){ 81 | if (st[u][i] != st[v][i]){ 82 | u = st[u][i];v = st[v][i]; 83 | } 84 | } 85 | assert(st[u][0] == st[v][0]); 86 | return st[u][0]; 87 | } 88 | //三度化 89 | int dfs(int u,int fa){ 90 | int now = ++cnt; 91 | id1[now] = idd1[u];dep1[now] = depp1[u]; 92 | pos1[id1[now]] = now; 93 | int pre = now; 94 | for (auto v : EE1[u]){ 95 | if (v == fa)continue; 96 | int temp = ++cnt; 97 | id1[temp] = 0;dep1[temp] = depp1[u]; 98 | edge_cnt ++; 99 | E1[pre].push_back(make_tuple(temp,dep1[temp] - dep1[pre],edge_cnt)); 100 | E1[temp].push_back(make_tuple(pre,dep1[temp] - dep1[pre],edge_cnt)); 101 | int vid = dfs(v,u); 102 | edge_cnt ++; 103 | E1[temp].push_back(make_tuple(vid,dep1[vid] - dep1[temp],edge_cnt)); 104 | E1[vid].push_back(make_tuple(temp,dep1[vid] - dep1[temp],edge_cnt)); 105 | pre = temp; 106 | } 107 | return now; 108 | } 109 | long long ans = 0; 110 | int sz[maxn*4]; 111 | int dis[maxn* 4]; 112 | void dfs_dis(int u,int fa,int len){ 113 | dis[u] = len; 114 | for (auto e : E1[u]){ 115 | int v,lll,edge_id;tie(v,lll,edge_id) = e; 116 | if (v == fa || !can_use[edge_id])continue; 117 | dfs_dis(v,u,len + lll); 118 | } 119 | } 120 | void dfs_sz(int u,int fa){ 121 | sz[u] = 1; 122 | for (auto e : E1[u]){ 123 | int v,len,edge_id;tie(v,len,edge_id) = e; 124 | if (v == fa || !can_use[edge_id])continue; 125 | dfs_sz(v,u); 126 | sz[u] += sz[v]; 127 | } 128 | } 129 | void dfs_edge(int u,int fa,int &e_id,int &uu,int &vv,int &ww,int &max_sz,int tot_node){ 130 | for (auto e : E1[u]){ 131 | int v,len,edge_id;tie(v,len,edge_id) = e; 132 | if (v == fa || !can_use[edge_id])continue; 133 | int max_sz_t = max(sz[v],tot_node - sz[v]); 134 | if (max_sz_t < max_sz){ 135 | max_sz = max_sz_t; 136 | uu = u;vv = v;ww = len;e_id = edge_id; 137 | } 138 | dfs_edge(v,u,e_id,uu,vv,ww,max_sz,tot_node); 139 | } 140 | } 141 | void dfs_node(int u,int fa,vector &nodes){ 142 | if (id1[u])nodes.push_back(id1[u]); 143 | for (auto e : E1[u]){ 144 | int v,len,edge_id;tie(v,len,edge_id) = e; 145 | if (v == fa || !can_use[edge_id])continue; 146 | dfs_node(v,u,nodes); 147 | } 148 | } 149 | int color[maxn * 2]; 150 | int vis[maxn]; 151 | long long dp[maxn * 2]; 152 | long long dp_cnt[maxn*2][2]; 153 | long long dp_sum[maxn*2][2]; 154 | int stk[maxn*2]; 155 | int fa[maxn*2]; 156 | inline void clear(int x,int type){ 157 | dp[x] = 0;vis[x] = type; 158 | for (int c = 0; c < 2;c ++)dp_cnt[x][c] = dp_sum[x][c] = 0; 159 | } 160 | void DP(vector & nodes_,int ww){ 161 | vector nodes(0); 162 | for (int x : nodes_){ 163 | nodes.push_back(pos2[x]); 164 | } 165 | for (int x : nodes)clear(x,1); 166 | sort(nodes.begin(),nodes.end(),[](int x,int y){ 167 | return l[x] < l[y]; 168 | }); 169 | int SZ = nodes.size(); 170 | for (int i=1;i r[stk[top-1]]) top --; 188 | fa[nodes[i]] = stk[top-1]; 189 | stk[top++] = nodes[i]; 190 | } 191 | long long anss = 0; 192 | for (int i= nodes.size() - 1;i >=0 ;i --){ 193 | int u = nodes[i], c = vis[u] == 1? color[id2[u]] - 1: -1; 194 | if (c != -1){ 195 | long long A = dep1[pos1[id2[u]]] - dis[pos1[id2[u]]]; 196 | dp[u] += A * dp_cnt[u][!c] + dp_sum[u][!c]; 197 | dp[u] -= dp_cnt[u][!c] * ww; 198 | dp_cnt[u][c] ++; 199 | dp_sum[u][c] += A; 200 | } 201 | long long temp_ans = dp[u] * dep2[u]; 202 | assert(temp_ans %2 == 0); 203 | anss += temp_ans/2; 204 | dp[fa[u]] += dp_cnt[fa[u]][0] * dp_sum[u][1] + dp_cnt[u][0] * dp_sum[fa[u]][1]; 205 | dp[fa[u]] += dp_cnt[fa[u]][1] * dp_sum[u][0] + dp_cnt[u][1] * dp_sum[fa[u]][0]; 206 | dp[fa[u]] -= (dp_cnt[fa[u]][1] * dp_cnt[u][0] + dp_cnt[fa[u]][0] * dp_cnt[u][1]) * ww; 207 | for (int c = 0;c < 2;c ++){ 208 | dp_cnt[fa[u]][c] += dp_cnt[u][c]; 209 | dp_sum[fa[u]][c] += dp_sum[u][c]; 210 | } 211 | } 212 | ans += anss; 213 | for (int x : nodes)vis[x] = 0; 214 | } 215 | void calc(int uu,int vv,int ww){ 216 | vector L(0),R(0),nodes(0); 217 | dfs_node(uu,0,L);dfs_node(vv,0,R); 218 | for (int x : L){color[x] = 1;nodes.push_back(x);} 219 | for (int x : R){color[x] = 2;nodes.push_back(x);} 220 | DP(nodes,ww); 221 | } 222 | void dfs(int root){ 223 | dfs_sz(root,0); 224 | int tot_node = sz[root]; 225 | if (tot_node == 1)return; 226 | int edge_id,uu,vv,ww,max_sz = tot_node + 1; 227 | dfs_edge(root,0,edge_id,uu,vv,ww,max_sz,tot_node); 228 | can_use[edge_id] = false; 229 | dfs_dis(uu,0,0);dfs_dis(vv,0,0); 230 | calc(uu,vv,ww);dfs(uu);dfs(vv); 231 | } 232 | int main(){ 233 | scanf("%s%d%d",s,&K1,&K2); 234 | n = strlen(s); 235 | memcpy(t,s,sizeof s);reverse(t,t + n); 236 | sam1.init(s);sam2.init(t); 237 | sam1.extract(EE1,s,n,idd1,depp1,K2); 238 | sam2.extract(E2,t,n,id2,dep2,K1); 239 | for (int i=1;i<= sam2.cnt; i ++){ 240 | if (id2[i]){ 241 | id2[i] = n + 1 - id2[i]; 242 | pos2[id2[i]] = i; 243 | } 244 | } 245 | int root1 = dfs(1,0);int root2 = 1; 246 | dfs2(root2,0); 247 | memset(can_use,true,sizeof can_use); 248 | dfs(root1); 249 | cout< 4 | using namespace std; 5 | const int maxn = 500000+100; 6 | int n,q,m,Root; char s[10]; 7 | struct BIT{ 8 | int sm[maxn]; 9 | int lowbit(int _x){return _x&(-_x);} 10 | void build (int l,int r){ 11 | for (int i=l;i<=r;i++)add(i,1); 12 | } 13 | void add(int x,int val){ 14 | while (x<=maxn){ 15 | sm[x]+=val;x+=lowbit(x); 16 | } 17 | } 18 | int sum(int x){ 19 | int res =0; 20 | while (x){ 21 | res+=sm[x]; 22 | x-=lowbit(x); 23 | } 24 | return res; 25 | } 26 | int query_sum(int l,int r){ 27 | return sum(r)-sum(l-1); 28 | } 29 | }tree; 30 | namespace Heavy_Light_Decomposition{ 31 | int first[maxn*2];int nxt[maxn*2];int des[maxn*2]; 32 | int tot,cnt=0; 33 | int tpos[maxn];int dep[maxn];int top[maxn]; 34 | int fa[maxn]; int wson[maxn]; int sz[maxn]; 35 | inline void addEdge(int _u, int _v){ 36 | des[++tot] = _v; 37 | nxt[tot] = first[_u]; 38 | first[_u] = tot; 39 | } 40 | //统计dep,子树sz,重儿子wson 41 | void dfs(int node,int father){ 42 | dep[node] = dep[father]+1; 43 | fa[node] = father; sz[node] =1; 44 | for (int t = first[node];t;t = nxt[t]){ 45 | int v = des[t]; 46 | if (v==father){ continue; } 47 | dfs(v,node); 48 | if (sz[v]>sz[wson[node]]){ 49 | wson[node] = v; 50 | } 51 | sz[node]+=sz[v]; 52 | } 53 | } 54 | //node所在链的头是chain 55 | void dfs2(int node,int father,int chain){ 56 | top[node] = chain; tpos[node] = ++cnt; 57 | if (wson[node]){ 58 | dfs2(wson[node],node,chain); 59 | } 60 | for (int t = first[node];t;t = nxt[t]){ 61 | int v = des[t]; 62 | if (v==father||v ==wson[node]){ continue; } 63 | dfs2(v,node,v); 64 | } 65 | } 66 | /* s 树根 */ 67 | void init(int root){ 68 | dfs(root,0); 69 | dfs2(root, 0, root); 70 | } 71 | int lca(int x,int y){ 72 | while (top[x]!=top[y]){ 73 | if (dep[top[x]] 6 | #include 7 | #include 8 | using namespace std; 9 | const int MAX = 1e4+100; 10 | const int INF = 0x3f3f3f3f; 11 | int first [MAX*2]; int des[MAX*2]; 12 | int len[MAX*2]; int nxt[MAX*2]; 13 | int n,k,tot; int a[MAX]; int sum[MAX]; 14 | int dp[MAX]; int dis[MAX]; int num,ans; 15 | bool vis[MAX]; int Sum,Min,Minid; 16 | void init(){ 17 | memset(first,0,sizeof first); 18 | tot =0; ans =0; 19 | memset(vis,0,sizeof vis); 20 | } 21 | inline void add(int x,int y,int z){ 22 | tot++; 23 | des[tot]= y; len[tot] =z; 24 | nxt[tot] = first[x]; first[x] = tot; 25 | } 26 | void input(){ 27 | for (int i=1;i 6 | using namespace std; 7 | typedef long long LL; 8 | const int maxn = 25e4+100; 9 | const LL INF = 0x3f3f3f3f3f3f3f3fLL; 10 | int first[maxn],des[maxn*2],nxt[maxn*2],tot; 11 | int n,m; 12 | LL dp[maxn],leng[maxn*2], len[maxn]; 13 | int vis[maxn],dep[maxn],fa[maxn]; 14 | int sz[maxn],wson[maxn],ttop[maxn],tfa[maxn];int k,h[maxn]; 15 | int stk[maxn],top;int l[maxn],r[maxn],dfs_clock; 16 | inline void addEdge(int x,int y,int w){ 17 | tot++; 18 | des[tot] = y;leng[tot] = w; 19 | nxt[tot] = first[x];first[x] = tot; 20 | } 21 | void dfs(int u,int fath){ 22 | l[u] = ++dfs_clock;sz[u]=1; 23 | for (int t = first[u];t;t=nxt[t]){ 24 | int v = des[t]; 25 | if (v==fath)continue; 26 | LL w = leng[t]; 27 | dep[v] = dep[u] + 1;tfa[v]=u; 28 | len[v] = min(len[u],w); 29 | dfs(v,u);sz[u]+=sz[v]; 30 | if (sz[v]>sz[wson[u]]){wson[u] = v;} 31 | } 32 | r[u]=dfs_clock ; 33 | } 34 | void dfs2(int u,int chain){ 35 | ttop[u]=chain; 36 | if (wson[u])dfs2(wson[u],chain); 37 | for (int t = first[u];t;t=nxt[t]){ 38 | int v = des[t]; 39 | if (v==tfa[u]||v==wson[u])continue; 40 | dfs2(v,v); 41 | } 42 | } 43 | int lca(int x,int y){ 44 | while (ttop[x]!=ttop[y]){ 45 | if (dep[ttop[x]]r[stk[top-1]])top--; 69 | fa[h[i]] = stk[top-1]; 70 | stk[top++] =h[i]; 71 | } 72 | for (int i=k-1;i>=0;i--){ 73 | if (vis[h[i]]==2)dp[h[i]] = min(dp[h[i]],len[h[i]]); 74 | else dp[h[i]] = len[h[i]]; 75 | dp[fa[h[i]]]+=dp[h[i]]; 76 | } 77 | printf("%lld\n",dp[1]); 78 | for (int i=0;i 3 | #define FOR(i,l,r) for (int i = (l);i<(r);i++) 4 | #define FORD(i,r,l) for (int i= (r);i>(l);i--) 5 | using namespace std; 6 | typedef long long LL; 7 | typedef vector V; 8 | const int MOD = 1e9+7; 9 | // k 为 m 最高次数 且 a[m] == 1 10 | namespace BerlekampMassey { 11 | inline void up(LL& a, LL b) { (a += b) %= MOD; } 12 | 13 | V mul(const V& a, const V& b, const V& m, int k) { 14 | V r; r.resize(2 * k - 1); 15 | FOR (i, 0, k) 16 | FOR (j, 0, k) 17 | up(r[i + j], a[i] * b[j]); 18 | FORD (i, k - 2, - 1) { 19 | FOR (j, 0, k) 20 | up(r[i + j], r[i + k] * m[j]); 21 | r.pop_back(); 22 | } 23 | return r; 24 | } 25 | LL pow_mod (LL x,LL y){ 26 | LL ret =1; 27 | for (;y;y>>=1){if (y&1) ret = ret*x%MOD;x = x * x %MOD;} 28 | return ret; 29 | } 30 | LL get_inv(LL x,LL MOD){ 31 | return pow_mod(x,MOD-2); 32 | } 33 | V pow(LL n, const V& m) { 34 | int k = (int)m.size() - 1; assert(m[k] == -1 || m[k] == MOD - 1); 35 | V r(k), x(k); r[0] = x[1] = 1; 36 | for (; n; n >>= 1, x = mul(x, x, m, k)) 37 | if (n & 1) r = mul(x, r, m, k); 38 | return r; 39 | } 40 | LL go(const V& a, const V& x, LL n) { 41 | // a: (-1, a1, a2, ..., ak).reverse 42 | // x: x1, x2, ..., xk 43 | // x[n] = sum[a[i]*x[n-i],{i,1,k}] 44 | int k = (int)a.size() - 1; 45 | if (n <= k) return x[n - 1]; 46 | V r = pow(n - 1, a); 47 | LL ans = 0; 48 | FOR (i, 0, k) 49 | up(ans, r[i] * x[i]); 50 | return ans; 51 | } 52 | 53 | V BM(const V& x) { 54 | V a = {-1}, b = {233}; 55 | FOR (i, 1, x.size()) { 56 | b.push_back(0); 57 | LL d = 0, la = a.size(), lb = b.size(); 58 | FOR (j, 0, la) up(d, a[j] * x[i - la + 1 + j]); 59 | if (d == 0) continue; 60 | V t; for (auto& v: b) t.push_back(d * v % MOD); 61 | FOR (j, 0, a.size()) up(t[lb - 1 - j], a[la - 1 - j]); 62 | if (lb > la) { 63 | b = a; 64 | LL inv = -get_inv(d, MOD); 65 | for (auto& v: b) v = v * inv % MOD; 66 | } 67 | a.swap(t); 68 | } 69 | for (auto& v: a) up(v, MOD); 70 | return a; 71 | } 72 | void sample(); 73 | } 74 | void BerlekampMassey::sample(){ 75 | V x(6); 76 | x[0] = 1;x[1] = 2; 77 | x[2] = 21;x[3] = 212; 78 | x[4] = 2141;x[5] = 21622; 79 | V a = BerlekampMassey::BM(x); 80 | cout<<"a[n] = "; 81 | for (int i = 0;i 5 | using namespace std; 6 | typedef long long ll; 7 | const int maxn = 1e5+100; 8 | namespace CRT{ 9 | ll ex_gcd(ll a,ll b,ll& x,ll& y){ 10 | if (b == 0){x = 1;y = 0;return a;} 11 | ll gcd = ex_gcd(b,a%b,x,y); 12 | ll t = x;x = y;y = t - a/b*y; 13 | return gcd; 14 | } 15 | ll mul_mod(ll a,ll b,ll m){ 16 | ll res = 0; 17 | while (b){ 18 | if (b&1){ 19 | res = (res + a) % m; 20 | } 21 | b >>=1; 22 | a = a * 2 % m; 23 | } 24 | return res; 25 | } 26 | // ans = first + t * second; 27 | // x = second (mod first) 28 | pairwork(vector >&es ){ 29 | ll ans = es[0].second; 30 | ll M = es[0].first; 31 | for (int i=1;i > es; 48 | int main(){ 49 | int n; 50 | scanf("%d",&n); 51 | for (int i=0;i ans = CRT::work(es); 57 | // cout< 3 | using namespace std; 4 | namespace fft { 5 | //attention data type 6 | typedef long long type; 7 | typedef double db; 8 | struct cp { 9 | db x, y; 10 | cp() { x = y = 0; } 11 | cp(db x, db y) : x(x), y(y) {} 12 | }; 13 | cp operator+(cp a, cp b) { return cp(a.x + b.x, a.y + b.y); } 14 | cp operator-(cp a, cp b) { return cp(a.x - b.x, a.y - b.y); } 15 | cp operator*(cp a, cp b) { return cp(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } 16 | cp conj(cp a) { return cp(a.x, -a.y); } 17 | type base = 1; 18 | vector roots = {{0, 0}, {1, 0}}; 19 | vector rev = {0, 1}; 20 | const db PI = acosl(-1.0); 21 | void ensure_base(type nbase) { 22 | if (nbase <= base) return; 23 | rev.resize(static_cast(1 << nbase)); 24 | for (type i = 0; i < (1 << nbase); i++) { 25 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1)); 26 | } 27 | roots.resize(static_cast(1 << nbase)); 28 | while (base < nbase) { 29 | db angle = 2 * PI / (1 << (base + 1)); 30 | for (type i = 1 << (base - 1); i < (1 << base); i++) { 31 | roots[i << 1] = roots[i]; 32 | db angle_i = angle * (2 * i + 1 - (1 << base)); 33 | roots[(i << 1) + 1] = cp(cos(angle_i), sin(angle_i)); 34 | } 35 | base++; 36 | } 37 | } 38 | void fft(vector &a, type n = -1) { 39 | if (n == -1) n = a.size(); 40 | assert((n & (n - 1)) == 0); 41 | type zeros = __builtin_ctz(n); 42 | ensure_base(zeros); 43 | type shift = base - zeros; 44 | for (type i = 0; i < n; i++) { 45 | if (i < (rev[i] >> shift)) { 46 | swap(a[i], a[rev[i] >> shift]); 47 | } 48 | } 49 | for (type k = 1; k < n; k <<= 1) { 50 | for (type i = 0; i < n; i += 2 * k) { 51 | for (type j = 0; j < k; j++) { 52 | cp z = a[i + j + k] * roots[j + k]; 53 | a[i + j + k] = a[i + j] - z; 54 | a[i + j] = a[i + j] + z; 55 | } 56 | } 57 | } 58 | } 59 | vector fa, fb; 60 | vector multiply(vector &a, vector &b) { 61 | type need = a.size() + b.size() - 1; 62 | type nbase = 0; 63 | while ((1 << nbase) < need) nbase++; 64 | ensure_base(nbase); 65 | type sz = 1 << nbase; 66 | if (sz > (type) fa.size()) 67 | fa.resize(static_cast(sz)); 68 | for (type i = 0; i < sz; i++) { 69 | type x = (i < (type) a.size() ? a[i] : 0); 70 | type y = (i < (type) b.size() ? b[i] : 0); 71 | fa[i] = cp(x, y); 72 | } 73 | fft(fa, sz); 74 | cp r(0, -0.25 / sz); 75 | for (type i = 0; i <= (sz >> 1); i++) { 76 | type j = (sz - i) & (sz - 1); 77 | cp z = (fa[j] * fa[j] - conj(fa[i] * fa[i])) * r; 78 | if (i != j) { 79 | fa[j] = (fa[i] * fa[i] - conj(fa[j] * fa[j])) * r; 80 | } 81 | fa[i] = z; 82 | } 83 | fft(fa, sz); 84 | vector res(static_cast(need)); 85 | for (type i = 0; i < need; i++) { 86 | res[i] = fa[i].x + 0.5; 87 | } 88 | return res; 89 | } 90 | vector multiply_mod(vector &a, vector &b, type m, type eq = 0) { 91 | type need = a.size() + b.size() - 1; 92 | type nbase = 0; 93 | while ((1 << nbase) < need) nbase++; 94 | ensure_base(nbase); 95 | type sz = 1 << nbase; 96 | if (sz > (type) fa.size()) { 97 | fa.resize(static_cast(sz)); 98 | } 99 | for (type i = 0; i < (type) a.size(); i++) { 100 | type x = (a[i] % m + m) % m; 101 | fa[i] = cp(x & ((1 << 15) - 1), x >> 15); 102 | } 103 | fill(fa.begin() + a.size(), fa.begin() + sz, cp {0, 0}); 104 | fft(fa, sz); 105 | if (sz > (type) fb.size()) { 106 | fb.resize(static_cast(sz)); 107 | } 108 | if (eq) { 109 | copy(fa.begin(), fa.begin() + sz, fb.begin()); 110 | } else { 111 | for (type i = 0; i < (type) b.size(); i++) { 112 | type x = (b[i] % m + m) % m; 113 | fb[i] = cp(x & ((1 << 15) - 1), x >> 15); 114 | } 115 | fill(fb.begin() + b.size(), fb.begin() + sz, cp {0, 0}); 116 | fft(fb, sz); 117 | } 118 | db ratio = 0.25 / sz; 119 | cp r2(0, -1);cp r3(ratio, 0); 120 | cp r4(0, -ratio);cp r5(0, 1); 121 | for (type i = 0; i <= (sz >> 1); i++) { 122 | type j = (sz - i) & (sz - 1); 123 | cp a1 = (fa[i] + conj(fa[j])); 124 | cp a2 = (fa[i] - conj(fa[j])) * r2; 125 | cp b1 = (fb[i] + conj(fb[j])) * r3; 126 | cp b2 = (fb[i] - conj(fb[j])) * r4; 127 | if (i != j) { 128 | cp c1 = (fa[j] + conj(fa[i])); 129 | cp c2 = (fa[j] - conj(fa[i])) * r2; 130 | cp d1 = (fb[j] + conj(fb[i])) * r3; 131 | cp d2 = (fb[j] - conj(fb[i])) * r4; 132 | fa[i] = c1 * d1 + c2 * d2 * r5; 133 | fb[i] = c1 * d2 + c2 * d1; 134 | } 135 | fa[j] = a1 * b1 + a2 * b2 * r5; 136 | fb[j] = a1 * b2 + a2 * b1; 137 | } 138 | fft(fa, sz);fft(fb, sz); 139 | vector res(static_cast(need)); 140 | for (type i = 0; i < need; i++) { 141 | long long aa = fa[i].x + 0.5; 142 | long long bb = fb[i].x + 0.5; 143 | long long cc = fa[i].y + 0.5; 144 | res[i] = (aa + ((bb % m) << 15) + ((cc % m) << 30)) % m; 145 | } 146 | return res; 147 | } 148 | vector square_mod(vector &a, type m) { 149 | return multiply_mod(a, a, m, 1); 150 | } 151 | }; 152 | const int maxn = 2e5+100; 153 | int n,x; 154 | int a[maxn],sum[maxn],cnt[maxn]; 155 | vector A,B,C; 156 | //example: 157 | //f[i] = number of subsequences whose occurence of 1 is i. 158 | //f[i] = \sum_{cnt[j]*cnt[j-i]} 159 | int main(){ 160 | scanf("%d%d",&n,&x);cnt[0]=1; 161 | for (int i=1;i<=n;i++){ 162 | scanf("%d",a+i); 163 | sum[i] =sum[i-1]; 164 | if(a[i]>=1; 173 | for (int i=n*2;i<=n*3;i++){ cout< 4 | using namespace std; 5 | typedef long long LL; 6 | const int N = 1048576;; 7 | const int MOD = 998244353; 8 | const int INV2 = (MOD+1)>>1; 9 | const int INV4 = 1LL*INV2*INV2%MOD; 10 | int a[N]; 11 | int n; 12 | //xor fwt : A[i] = \sigma{-1^([i&j])*a[j]} [x]:count of 1-bit 13 | void FWT(int *a,int n,int r){ 14 | for (int i=1;i>=1){if (y&1) ret = ret*x%MOD;x = x*x%MOD;} 32 | return ret; 33 | } 34 | int main(){ 35 | scanf("%d",&n); 36 | for (int i=1;i<=n;i++){ 37 | int x;scanf("%d",&x); 38 | a[x]++; 39 | } 40 | FWT(a,N,1); 41 | for(int i=0;i 5 | using namespace std; 6 | const int MAXN = 100; 7 | struct Matrix{ 8 | // a[0..n-1] 表示一个方程 9 | // a[][0 .. m-2] 表示有m-1个未知数,每行是对应的系数 10 | // a[][m-1]是等式右边的值。 11 | double a[MAXN][MAXN], n, m; 12 | void gauss(){ 13 | for (int i = 0; i < n; i++){ 14 | int k = i; 15 | for (int j = i + 1; j < n; j++){ 16 | if (abs(a[j][i]) > abs(a[k][i]))k = j; 17 | } 18 | for (int j = i; j < m; j++) 19 | swap(a[i][j], a[k][j]); 20 | for (int j = i + 1; j < n; j++){ 21 | double r = a[j][i] / a[i][i]; 22 | for (int k = i + 1; k < m; k++) 23 | a[j][k] -= r*a[i][k]; 24 | } 25 | } 26 | for (int i = n - 1; i >= 0; i--){ 27 | for (int k = n; k < m; k++){ 28 | for (int j = i + 1; j < n; j++) 29 | a[i][k] -= a[i][j] * a[j][k]; 30 | a[i][k] /= a[i][i]; 31 | } 32 | } 33 | } 34 | double det(){ 35 | int s = 0; 36 | for (int i = 0; i < n; i++){ 37 | int k = i; 38 | for (int j = i + 1; j < n; j++){ 39 | if (abs(a[j][i]) > abs(a[k][i]))k = j; 40 | } 41 | s += k == i; 42 | for (int j = i; j < m; j++) 43 | swap(a[i][j], a[k][j]); 44 | for (int j = i + 1; j < n; j++){ 45 | double r = a[j][i] / a[i][i]; 46 | for (int k = i + 1; k < m; k++) 47 | a[j][k] -= r*a[i][k]; 48 | } 49 | } 50 | double ret = 1; 51 | for (int i = 0; i < n; i++) 52 | ret *= a[i][i]; 53 | return s & 1 ? -ret : ret; 54 | } 55 | }; 56 | int main(){ 57 | Matrix mat; 58 | mat.a[0][0] = 1;mat.a[0][1] = 2;mat.a[0][2] = 3;mat.a[0][3] = 100; 59 | mat.a[1][0] = 1;mat.a[1][1] = 1;mat.a[1][2] = 0;mat.a[1][3] = 20; 60 | mat.a[2][0] = 1;mat.a[2][1] = 0;mat.a[2][2] = 1;mat.a[2][3] = 10; 61 | mat.n = 3; 62 | mat.m = 4; 63 | mat.gauss(); 64 | for (int i=0;i<3;i++){ 65 | cerr< 7 | using namespace std; 8 | int s[maxn]; 9 | int n; 10 | struct Linear_Basis{ 11 | //basis vector 12 | int basis[22]; 13 | //basis vector in origin data 14 | int num[22]; 15 | void clear(){ 16 | memset(basis,0,sizeof basis); 17 | memset(num,0,sizeof num); 18 | } 19 | void ins(int x){ 20 | int bk = x; 21 | for (int i=20;i>=0;i--){ 22 | if (x & (1<< i)){ 23 | if (!basis[i]){basis[i] = x;num[i] = bk;break;} 24 | x ^= basis[i]; 25 | } 26 | } 27 | } 28 | int count(){ 29 | int cnt = 0; 30 | for (int i=0;i<=20;i++){ 31 | cnt += (basis[i] != 0); 32 | } 33 | return cnt; 34 | } 35 | void debug(){ 36 | _debug("basis : "); 37 | for (int i=0;i<=20;i++){ 38 | if (basis[i])_debug("%d : %d",i,basis[i]); 39 | } 40 | } 41 | }basis; 42 | int main(){ 43 | cin>>n; 44 | for (int i=1;i<=n;i++){ 45 | cin>>s[i]; 46 | basis.ins(s[i]); 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /Math/Matrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const double EPS = 1e-18; 4 | template 5 | inline bool is_zero(Type value){ 6 | return fabs(value) <= EPS; 7 | } 8 | 9 | template 10 | class Matrix{ 11 | private: 12 | vector > data; 13 | public: 14 | int width,height; 15 | Matrix(int height=0,int width=0,Type value = 0); 16 | Matrix (const Matrix & other); 17 | Matrix operator + (const Matrix & other); 18 | Matrix operator - (const Matrix & other); 19 | Matrix operator * (const Matrix & other); 20 | Matrix operator ~(); 21 | vector operator [](int row)const; 22 | vector& operator [] (int row); 23 | void print(); 24 | static Matrix eye(int n); 25 | }; 26 | typedef Matrix Mat; 27 | template 28 | Matrix::Matrix(const Matrix & other){ 29 | height = other.height; 30 | width = other.width; 31 | data = other.data; 32 | } 33 | template 34 | Matrix::Matrix(int height_,int width_,Type value_){ 35 | height = height_; 36 | width = width_; 37 | data.resize(height); 38 | for (int i=0;i< height;i++){ 39 | data[i].resize(width,value_); 40 | } 41 | } 42 | template 43 | void Matrix::print(){ 44 | for (int i=0;i 52 | Matrix Matrix :: operator + (const Matrix & other){ 53 | if (other.height != height || other.width != width){ 54 | throw -1; 55 | } 56 | Matrix res(height,width); 57 | for (int i=0;i< height;i++){ 58 | for (int j=0;j< width;j++){ 59 | res.data[i][j] = data[i][j] + other.data[i][j]; 60 | } 61 | } 62 | return res; 63 | } 64 | template 65 | Matrix Matrix :: operator - (const Matrix & other){ 66 | if (other.height != height || other.width != width){ 67 | throw -1; 68 | } 69 | Matrix res(height,width); 70 | for (int i=0;i< height;i++){ 71 | for (int j=0;j< width;j++){ 72 | res.data[i][j] = data[i][j] - other.data[i][j]; 73 | } 74 | } 75 | return res; 76 | } 77 | template 78 | Matrix Matrix :: operator * (const Matrix & other){ 79 | if ( other.height != width){ 80 | throw -2; 81 | } 82 | Matrix res(height,other.width); 83 | for (int i=0;i< height;i++){ 84 | for (int j=0;j< other.width;j++){ 85 | for (int k=0;k 93 | Matrix Matrix:: operator ~(){ 94 | int h = height; 95 | int w = width; 96 | Matrix res(w,h); 97 | for (int i=0;i 105 | vector Matrix :: operator[](int row)const{ 106 | cout< height){ 108 | throw -5; 109 | } 110 | return data[row]; 111 | } 112 | template 113 | vector& Matrix :: operator[](int row){ 114 | if (row > height){ 115 | throw -5; 116 | } 117 | return data[row]; 118 | } 119 | template 120 | Matrix Matrix :: eye(int n){ 121 | Matrix res(n,n); 122 | for (int i=0;i 3 | #include 4 | using namespace std; 5 | const int maxn = 1e5+100; 6 | typedef long long ll; 7 | bool used[maxn]; 8 | vector prime; 9 | ll mu[maxn]; 10 | void sieve(){ 11 | mu[1] = 1; 12 | for (int i=2;i= maxn)break; 20 | used[nxt] = 1; 21 | if (i % prime[j] == 0){ 22 | mu[nxt] = 0; 23 | break; 24 | }else{ 25 | mu[nxt] = -mu[i]; 26 | } 27 | } 28 | } 29 | } 30 | ll work(int n,int m){ 31 | ll ans = 0; 32 | int top = min(n,m); 33 | for (int i=1;i<=top;i++){ 34 | ans += 1ll * mu[i] * (n/i) * (m/i); 35 | } 36 | return ans; 37 | } 38 | int main(){ 39 | sieve(); 40 | int T; 41 | scanf("%d",&T); 42 | for (int Case = 1;Case <= T;Case ++){ 43 | int a,b,n,m,k; 44 | scanf("%d%d%d%d%d",&a,&n,&b,&m,&k); 45 | if(k == 0){ 46 | printf("Case %d: 0\n",Case); 47 | continue; 48 | } 49 | n/=k; 50 | m/=k; 51 | printf("Case %d: %lld\n",Case,work(n,m) - work(min(n,m),min(n,m))/2); 52 | } 53 | return 0; 54 | } -------------------------------------------------------------------------------- /Math/linear_sieve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int maxn = 1e7+10; 4 | typedef long long ll; 5 | bool used[maxn]; 6 | int mu[maxn]; 7 | vector prime; 8 | ll f[maxn]; 9 | int low[maxn]; 10 | void sieve(int size){ 11 | //f:multiplicative function; 12 | assert(size < maxn); 13 | mu[1] = 1; 14 | f[1] = 1; 15 | for (int i=2;i<=size;i++){ 16 | if (!used[i]){ 17 | prime.push_back(i); 18 | mu[i] = -1; 19 | //f:TODO 20 | low[i] = i; 21 | } 22 | for (int j = 0;j < prime.size();j++){ 23 | ll nxt = 1ll * i * prime[j]; 24 | if (nxt > size)break; 25 | used[nxt] = 1; 26 | if (i % prime[j]){ 27 | low[nxt] = prime[j]; 28 | mu[nxt] = -mu[i]; 29 | //f: mod or not? 30 | f[nxt] = f[i] * f[prime[j]]; 31 | }else{ 32 | low[nxt] = prime[j] * low[i]; 33 | mu[nxt] = 0; 34 | if (low[nxt] != nxt){ 35 | //mod or not? 36 | f[nxt] = 1ll * f[low[nxt]] * f[nxt/low[nxt]]; 37 | }else{ 38 | // i = prime[j] ^ k 39 | //f:TODO 40 | } 41 | break; 42 | } 43 | } 44 | } 45 | } 46 | int main(){ 47 | sieve(1e7); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /Others/Header.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy 2 | #pragma GCC optimize(3) 3 | #include 4 | using namespace std; 5 | #ifdef __LOCAL_DEBUG__ 6 | # define _debug(fmt, ...) fprintf(stderr, "\033[91m[%s %3d]: " fmt "\n\033[0m", \ 7 | __func__,__LINE__, ##__VA_ARGS__) 8 | #else 9 | # define _debug(...) (void(0)) 10 | #endif 11 | #define PB(x) push_back(x) 12 | #define rep(i,l,r) for (int i = l,_ = r;i< _;i++) 13 | #define REP(i,l,r) for (int i=l,_=r;i<=_;i++) 14 | #define leave(x) do {cout<<#x< vi; 20 | typedef vector vl; 21 | typedef long double db; 22 | typedef pair pii; 23 | typedef pair pll; 24 | const int inf = 0x3f3f3f3f; 25 | const ll inf_ll = 0x3f3f3f3f3f3f3f3fLL; 26 | mt19937 wdy(time(0)); 27 | /************* header ******************/ 28 | int main(){ 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Others/formula.txt: -------------------------------------------------------------------------------- 1 | C(n,m)%2 = (n&m)==m 2 | 约瑟夫问题: 3 | F(n,m) = 有n个人(0,1,2,..,n-1),每次杀掉编号为(x + m) %n的人,最终的幸存者。 4 | F(n,m) = (F(n-1,m) + m ) % n 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACM-Code-Library 2 | 3 | **calabash_boy's personal programming contest code library.** 4 | 5 | **This is a Clion project, so you can open it in Clion directly.** 6 | 7 | ## Blog:[calabash_boy](http://blog.csdn.net/calabash_boy) 8 | 9 | ## Team Wiki:[Calabash!](http://wiki-calabash.icpc.camp) 10 | 11 | ## Release PDF:[releases](http://github.com/4thcalabash/code_library/releases) 12 | -------------------------------------------------------------------------------- /String/Automaton/Aho-Corasick_Automaton.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 18-6-5. 2 | // HDU 6138 3 | //给定若干字典串。 4 | // query:strx stry 求最长的p,p为strx、stry子串,且p为某字典串的前缀 5 | #include 6 | using namespace std; 7 | const int maxn = 1e5+100; 8 | struct Aho_Corasick_Automaton{ 9 | //basic 10 | int nxt[maxn*10][26],fail[maxn*10]; 11 | int root,tot; 12 | //special 13 | int flag[maxn*10]; 14 | int len[maxn*10]; 15 | void clear(){ 16 | memset(nxt[0],0,sizeof nxt[0]); 17 | root = tot=0; 18 | } 19 | int newnode(){ 20 | tot++; 21 | memset(nxt[tot],0,sizeof nxt[tot]); 22 | flag[tot] = len[tot]=0; 23 | return tot; 24 | } 25 | void insert(char *s ){ 26 | int now = root; 27 | while (*s){ 28 | int id = *s-'a'; 29 | if(!nxt[now][id])nxt[now][id] = newnode(); 30 | len[nxt[now][id]] = len[now]+1; 31 | now = nxt[now][id]; 32 | } 33 | } 34 | void insert(string str){ 35 | int now = root; 36 | for (int i=0;iQ;Q.push(root); 46 | while (!Q.empty()){ 47 | int head = Q.front();Q.pop(); 48 | for (int i=0;i<26;i++){ 49 | if(!nxt[head][i])continue; 50 | int temp = nxt[head][i]; 51 | fail[temp] = fail[head]; 52 | while (fail[temp]&&!nxt[fail[temp]][i]){ 53 | fail[temp] = fail[fail[temp]]; 54 | } 55 | if(head&&nxt[fail[temp]][i])fail[temp] = nxt[fail[temp]][i]; 56 | Q.push(temp); 57 | } 58 | } 59 | } 60 | void search(string str,int QID); 61 | int query(string str,int QID); 62 | }acam; 63 | void Aho_Corasick_Automaton::search(string str,int QID) { 64 | int now = root; 65 | for (int i=0;i>T; 94 | while (T--){ 95 | acam.clear();cin>>n; 96 | for (int i=1;i<=n;i++){ 97 | cin>>a[i]; 98 | acam.insert(a[i]); 99 | } 100 | acam.build();cin>>m; 101 | for (int i=1;i<=m;i++){ 102 | int x,y;cin>>x>>y; 103 | qid++; 104 | acam.search(a[x],qid); 105 | int ans = acam.query(a[y],qid); 106 | cout< 6 | using namespace std; 7 | const int maxn = 5e5 + 100; 8 | typedef long long ll; 9 | struct Suffix_Automaton{ 10 | int nxt[maxn*2][26],fa[maxn*2],l[maxn*2]; 11 | bool vis[maxn*2]; 12 | int dirNxt[maxn*2][26]; 13 | int dirLen[maxn*2][26]; 14 | int ed[maxn*2]; 15 | vector > lens[maxn*2]; 16 | int last,cnt; 17 | void clear(){ 18 | last =cnt=1; 19 | fa[1]=l[1]=0; 20 | memset(nxt[1],0,sizeof nxt[1]); 21 | } 22 | void init(string s){ 23 | for (int c : s)add(c - 'a'); 24 | for (int i=0;i<=cnt;i++){ 25 | vis[i] = false; 26 | ed[i] = -1; 27 | lens[i].clear(); 28 | memset(dirLen[i],0,sizeof dirLen[i]); 29 | memset(dirNxt[i],0,sizeof dirNxt[i]); 30 | } 31 | } 32 | void add(int c){ 33 | int p = last; 34 | int np = ++cnt; 35 | memset(nxt[cnt],0,sizeof nxt[cnt]); 36 | l[np] = l[p]+1;last = np; 37 | while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p]; 38 | if (!p)fa[np]=1; 39 | else{ 40 | int q = nxt[p][c]; 41 | if (l[q]==l[p]+1)fa[np] =q; 42 | else{ 43 | int nq = ++ cnt; 44 | l[nq] = l[p]+1; 45 | memcpy(nxt[nq],nxt[q],sizeof (nxt[q])); 46 | fa[nq] =fa[q];fa[np] = fa[q] =nq; 47 | while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p]; 48 | } 49 | } 50 | } 51 | int find_nxt(int u){ 52 | int res = -1; 53 | for (int ch = 0;ch < 26;ch ++){ 54 | int v = nxt[u][ch]; 55 | if (!v)continue; 56 | if (res == -1)res = ch; 57 | else return -1; 58 | } 59 | return res; 60 | } 61 | void dfs(int u){ 62 | vis[u] = true; 63 | for (int ch = 0;ch < 26;ch ++){ 64 | int v = nxt[u][ch]; 65 | if (!v)continue; 66 | if (!vis[v])dfs(v); 67 | int dirch = find_nxt(v); 68 | if(dirch == -1){ 69 | dirNxt[u][ch] = v; 70 | dirLen[u][ch] = 1; 71 | }else{ 72 | dirNxt[u][ch] = dirNxt[v][dirch]; 73 | dirLen[u][ch] = dirLen[v][dirch] + 1; 74 | } 75 | if (find_nxt(u) == -1 or u == 1)lens[dirNxt[u][ch]].push_back(make_pair(dirLen[u][ch],u == 1?1:l[u] - l[fa[u]])); 76 | }; 77 | } 78 | void build(string s,Suffix_Automaton & sam_t){ 79 | int temp = 1; 80 | for(int i=0;i cnt(1,0); 97 | for (int c : t){ 98 | sam_t.add(c - 'a'); 99 | cnt.push_back(cnt.back() + sam_t.l[sam_t.last] - sam_t.l[sam_t.fa[sam_t.last]]); 100 | } 101 | for (auto x : lens[i])ans += cnt[x.first] * x.second; 102 | } 103 | cout<>T; 109 | while (T--){ 110 | string s; 111 | cin>>s; 112 | sam.clear(); 113 | sam.init(s); 114 | sam.dfs(1); 115 | sam.build(s,temp_sam); 116 | } 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /String/Automaton/Count_Substrings_In_Segment.cpp: -------------------------------------------------------------------------------- 1 | /* Created by calabash_boy on 19-12-4. 2 | * tutorial: 3 | *https://codeforces.com/blog/entry/62331?tdsourcetag=s_pctim_aiomsg 4 | */ 5 | #include 6 | using namespace std; 7 | typedef long long ll; 8 | const int maxn = 1e5 + 100; 9 | /* 维护最后出现位置在i(左端点)的本质不同串数量 */ 10 | struct SegmentTree_Sum{ 11 | ll Sum[maxn * 8],Lazy[maxn*8]; 12 | void down(int x,int l,int mid,int r){ 13 | Sum[x<<1] += Lazy[x] * (mid - l + 1); 14 | Sum[x<<1|1] += Lazy[x] * (r - mid); 15 | Lazy[x<<1] += Lazy[x]; 16 | Lazy[x<<1|1] += Lazy[x]; 17 | Lazy[x] = 0; 18 | } 19 | void up(int x){Sum[x] = Sum[x<<1] + Sum[x<<1|1];} 20 | void update(int x,int l,int r,int L,int R,int val){ 21 | if (l > R or L > r)return; 22 | if (L <= l and r <= R){ 23 | Sum[x] += 1ll * val * (r - l + 1); 24 | Lazy[x] += val; 25 | return; 26 | } 27 | int mid = l + r >> 1;down(x,l,mid,r); 28 | update(x<<1,l,mid,L,R,val);update(x<<1|1,mid+1,r,L,R,val); 29 | up(x); 30 | } 31 | ll query(int x,int l,int r,int L,int R){ 32 | if (l > R or L > r)return 0; 33 | if (L <= l and r <= R)return Sum[x]; 34 | int mid = l + r >> 1;down(x,l,mid,r); 35 | return query(x<<1,l,mid,L,R) + query(x<<1|1,mid+1,r,L,R); 36 | } 37 | }segtree; 38 | struct SegmentTree_Max{ 39 | int Max[maxn*8]; 40 | void update(int x,int l,int r,int pos,int val){ 41 | Max[x] = max(Max[x],val); 42 | if (l == r)return; 43 | int mid = l + r >> 1; 44 | if (pos <= mid)update(x<<1,l,mid,pos,val); 45 | else update(x<<1|1,mid+1,r,pos,val); 46 | } 47 | int query(int x,int l,int r,int L,int R){ 48 | if (l > R or L > r)return -1; 49 | if (L <= l and r <= R)return Max[x]; 50 | int mid = l + r >> 1; 51 | return max(query(x<<1,l,mid,L,R),query(x<<1|1,mid+1,r,L,R)); 52 | } 53 | }dfstree; 54 | int n,q; 55 | char s[maxn]; 56 | ll ans[maxn]; 57 | typedef pair,int> Query; 58 | vector query; 59 | struct Suffix_Automaton{ 60 | int nxt[maxn*2][26],fa[maxn*2],l[maxn*2]; 61 | int last,cnt; 62 | /* 每个color最上边一个点 */ 63 | int up_to[maxn]; 64 | /* 是否被染过色 */ 65 | bool used[maxn*2]; 66 | Suffix_Automaton(){ clear(); } 67 | void clear(){ 68 | last =cnt=1;fa[1]=l[1]=0; 69 | memset(nxt[1],0,sizeof nxt[1]); 70 | } 71 | void init(char *s){ 72 | while (*s){add(*s-'a');s++;} 73 | } 74 | void add(int c){ 75 | int p = last; 76 | int np = ++cnt; 77 | memset(nxt[cnt],0,sizeof nxt[cnt]); 78 | l[np] = l[p]+1;last = np; 79 | while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p]; 80 | if (!p)fa[np]=1; 81 | else{ 82 | int q = nxt[p][c]; 83 | if (l[q]==l[p]+1)fa[np] =q; 84 | else{ 85 | int nq = ++ cnt; 86 | l[nq] = l[p]+1; 87 | memcpy(nxt[nq],nxt[q],sizeof (nxt[q])); 88 | fa[nq] =fa[q];fa[np] = fa[q] =nq; 89 | while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p]; 90 | } 91 | } 92 | } 93 | vector E[maxn * 2]; 94 | int in[maxn*2],out[maxn*2],dfn; 95 | void dfs(int u){ 96 | in[u] = ++dfn; 97 | for (int v:E[u])dfs(v); 98 | out[u] = dfn; 99 | } 100 | void gao(){ 101 | for (int i=2;i<=cnt;i++)E[fa[i]].push_back(i); 102 | dfs(1); 103 | for (int i=1,now = 1;i<=n;i++){ 104 | now = nxt[now][s[i] - 'a']; 105 | assert(l[now] == i); 106 | segtree.update(1,1,n,1,i,1); 107 | int u = now; 108 | while (u != 1 and !used[u]){ 109 | used[u] = true; 110 | u = fa[u]; 111 | } 112 | while (u != 1){ 113 | int cur = dfstree.query(1,1,cnt,in[u],out[u]); 114 | segtree.update(1,1,n,cur - l[u]+1,cur - l[up_to[cur]],-1); 115 | swap(up_to[cur],u); 116 | } 117 | dfstree.update(1,1,cnt,in[now],i); 118 | up_to[i] = 1; 119 | while (!query.empty() and query.back().first.second == i){ 120 | int l = query.back().first.first; 121 | int id = query.back().second; 122 | ans[id] = segtree.query(1,1,n,l,i); 123 | query.pop_back(); 124 | } 125 | } 126 | } 127 | }sam; 128 | int main(){ 129 | cin>>n>>q; 130 | cin>>s+1; 131 | sam.init(s+1); 132 | for (int i=1;i<=q;i++){ 133 | int l,r; 134 | cin>>l>>r; 135 | query.push_back({{l+1,r+1},i}); 136 | } 137 | sort(query.begin(),query.end(),[](Query x,Query y){ 138 | return x.first.second > y.first.second; 139 | }); 140 | sam.gao(); 141 | for (int i=1;i<=q;i++){ 142 | cout< 4 | using namespace std; 5 | const int mod = 998244353; 6 | int lastans = 0; 7 | const int maxn = 5e5+100; 8 | int st[maxn][20]; 9 | int pos[maxn]; 10 | map score; 11 | char a[maxn]; 12 | int sum[maxn]; 13 | int get_anc(int x,int len){ 14 | while (len){ 15 | int bit = __builtin_ctz(len); 16 | x = st[x][bit]; 17 | len ^= (1 << bit); 18 | } 19 | return x; 20 | } 21 | int Damage[maxn]; 22 | struct Palindromic_AutoMaton{ 23 | //basic 24 | int now; 25 | int nxt[maxn][26],fail[maxn],l[maxn],tot; 26 | int damage[maxn]; 27 | int damage_sum[maxn]; 28 | int total[maxn]; 29 | int Link[maxn][26]; 30 | // extension 31 | int num[maxn];/*节点代表的所有回文串出现次数*/ 32 | void clear(){ 33 | //1节点:奇数长度root 0节点:偶数长度root 34 | l[1]=-1; 35 | fail[0] = tot = now =1; 36 | l[0]=0; 37 | memset(nxt[0],0,sizeof nxt[0]); 38 | memset(nxt[1],0,sizeof nxt[1]); 39 | for (int i = 0;i < 26;i ++)Link[1][i]=1,Link[0][i] = 1; 40 | } 41 | Palindromic_AutoMaton(){clear();} 42 | int newnode(int ll){ 43 | tot++; 44 | memset(nxt[tot],0,sizeof nxt[tot]); 45 | fail[tot]=num[tot]=0; 46 | l[tot]=ll; 47 | return tot; 48 | } 49 | int add(int i,int F,int last,int ch){ 50 | int cur = Link[last][ch]; 51 | if (a[get_anc(i,l[last]+1)] - 'A' == ch){ 52 | cur = last; 53 | } 54 | if(!nxt[cur][ch]){ 55 | int tt = newnode(l[cur]+2); 56 | fail[tt] = nxt[Link[cur][ch]][ch]; 57 | nxt[cur][ch] = tt; 58 | memcpy(Link[tt],Link[fail[tt]],sizeof Link[tt]); 59 | 60 | int u = get_anc(i,l[fail[tt]]); 61 | 62 | Link[tt][a[u] - 'A'] = fail[tt]; 63 | 64 | damage[tt] = sum[i] - sum[get_anc(i,l[tt])]; 65 | damage_sum[tt] = (damage_sum[fail[tt]] + damage[tt])% mod; 66 | } 67 | last = nxt[cur][ch];num[last]++; 68 | return last; 69 | } 70 | }pam; 71 | char buf[10]; 72 | int main(){ 73 | int _; 74 | scanf("%d",&_); 75 | score['A'] = _; 76 | scanf("%d",&_); 77 | score['C'] = _; 78 | scanf("%d",&_); 79 | score['G'] = _; 80 | scanf("%d",&_); 81 | score['U'] = _; 82 | scanf("%s",buf); 83 | a[1] = buf[0]; 84 | a[0] = 'Z'; 85 | sum[1] = score[buf[0]]; 86 | pos[0] = 1; 87 | pos[1] = pam.add(1,0,1,buf[0] - 'A'); 88 | lastans = pam.damage[pos[1]]; 89 | printf("%d\n",lastans); 90 | int total = lastans; 91 | for (int i = 2;;i ++){ 92 | int F; 93 | scanf("%d",&F); 94 | F ^= lastans; 95 | if (!F)break; 96 | scanf("%s",buf); 97 | a[i] = buf[0]; 98 | sum[i] = sum[F] + score[buf[0]]; 99 | st[i][0] = F; 100 | for (int step = 1;step < 20 and st[i][step-1];step ++){ 101 | st[i][step] = st[st[i][step-1]][step-1]; 102 | } 103 | pos[i] = pam.add(i,F,pos[F],buf[0] - 'A'); 104 | Damage[i] = pam.damage_sum[pos[i]] % mod; 105 | (total += Damage[i]) %= mod; 106 | printf("%d\n",lastans = pam.damage[pos[i]]); 107 | } 108 | printf("%d\n",total); 109 | return 0; 110 | } -------------------------------------------------------------------------------- /String/Automaton/Generalized_Suffix_Automaton.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 19-4-5. 2 | //wf2019 first of her name 3 | //build sam using trie 4 | #include 5 | using namespace std; 6 | const int maxn = 1e6+100; 7 | typedef long long ll; 8 | struct Suffix_Automaton{ 9 | int nxt[maxn*2][26],fa[maxn*2],l[maxn*2]; 10 | int last,cnt; 11 | vector E[maxn*2]; 12 | int Num[maxn*2]; 13 | Suffix_Automaton(){ clear(); } 14 | void clear(){ 15 | last =cnt=1; 16 | fa[1]=l[1]=0; 17 | memset(nxt[1],0,sizeof nxt[1]); 18 | } 19 | int add(int pre,int c,int num){ 20 | last = pre; 21 | int p = last; 22 | int np = ++cnt; 23 | Num[np] = num; 24 | memset(nxt[cnt],0,sizeof nxt[cnt]); 25 | l[np] = l[p]+1;last = np; 26 | while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p]; 27 | if (!p)fa[np]=1; 28 | else{ 29 | int q = nxt[p][c]; 30 | if (l[q]==l[p]+1)fa[np] =q; 31 | else{ 32 | int nq = ++ cnt; 33 | l[nq] = l[p]+1; 34 | memcpy(nxt[nq],nxt[q],sizeof (nxt[q])); 35 | fa[nq] =fa[q];fa[np] = fa[q] =nq; 36 | while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p]; 37 | } 38 | } 39 | return np; 40 | } 41 | int dfsl[maxn*2],dfsr[maxn*2]; 42 | int dfn = 0; 43 | ll sum[maxn*2]; 44 | void dfs(int u){ 45 | dfsl[u] = ++dfn; 46 | sum[dfn] = Num[u]; 47 | for (int v : E[u]){ 48 | dfs(v); 49 | } 50 | dfsr[u] = dfn; 51 | } 52 | void build(){ 53 | for (int i=2;i<=cnt;i++){ 54 | E[fa[i]].push_back(i); 55 | } 56 | dfs(1); 57 | for (int i=1;i<=cnt;i++){ 58 | sum[i] += sum[i-1]; 59 | } 60 | } 61 | void query(char * s){ 62 | int temp = 1; 63 | while (*s){ 64 | int ch = *s - 'A'; 65 | if (!nxt[temp][ch]){ 66 | printf("0\n"); 67 | return; 68 | } 69 | temp = nxt[temp][ch]; 70 | s++; 71 | } 72 | ll ans = sum[dfsr[temp]] - sum[dfsl[temp] - 1]; 73 | printf("%lld\n",ans); 74 | } 75 | }sam; 76 | struct Trie{ 77 | int Root = 1; 78 | int cnt = 2; 79 | int nxt[maxn][26]; 80 | int num[maxn]; 81 | int sam_pos[maxn]; 82 | int add(int p,int ch){ 83 | if (!nxt[p][ch]){ 84 | nxt[p][ch] = cnt++; 85 | } 86 | int now = nxt[p][ch]; 87 | num[now] ++; 88 | return now; 89 | } 90 | void bfs(){ 91 | queue Q; 92 | Q.push(1); 93 | sam_pos[1] = 1; 94 | while (!Q.empty()){ 95 | int head = Q.front(); 96 | Q.pop(); 97 | for (int i=0;i<26;i++){ 98 | if (!nxt[head][i])continue; 99 | int now = nxt[head][i]; 100 | sam_pos[now] = sam.add(sam_pos[head],i,num[now]); 101 | Q.push(now); 102 | } 103 | } 104 | } 105 | }trie; 106 | int trie_pos[maxn]; 107 | int main(){ 108 | int n,k; 109 | scanf("%d%d",&n,&k); 110 | trie_pos[0] = 1; 111 | for (int i=1;i<=n;i++){ 112 | static char s[5]; 113 | int p; 114 | scanf("%s%d",s,&p); 115 | int ch = s[0] - 'A'; 116 | trie_pos[i] = trie.add(trie_pos[p],ch); 117 | } 118 | trie.bfs(); 119 | sam.build(); 120 | for (int i=0;i 5 | using namespace std; 6 | const int maxn = 3e5+100; 7 | struct Palindromic_AutoMaton{ 8 | //basic 9 | int s[maxn],now; 10 | int nxt[maxn][26],fail[maxn],l[maxn],last,tot; 11 | // extension 12 | int num[maxn];/*节点代表的所有回文串出现次数*/ 13 | void clear(){ 14 | //1节点:奇数长度root 0节点:偶数长度root 15 | s[0]=l[1]=-1; 16 | fail[0] = tot = now =1; 17 | last = l[0]=0; 18 | memset(nxt[0],0,sizeof nxt[0]); 19 | memset(nxt[1],0,sizeof nxt[1]); 20 | } 21 | Palindromic_AutoMaton(){clear();} 22 | int newnode(int ll){ 23 | tot++; 24 | memset(nxt[tot],0,sizeof nxt[tot]); 25 | fail[tot]=num[tot]=0; 26 | l[tot]=ll; 27 | return tot; 28 | } 29 | int get_fail(int x){ 30 | while (s[now-l[x]-2]!=s[now-1])x = fail[x]; 31 | return x; 32 | } 33 | void add(int ch){ 34 | s[now++] = ch; 35 | int cur = get_fail(last); 36 | if(!nxt[cur][ch]){ 37 | int tt = newnode(l[cur]+2); 38 | fail[tt] = nxt[get_fail(fail[cur])][ch]; 39 | nxt[cur][ch] = tt; 40 | } 41 | last = nxt[cur][ch];num[last]++; 42 | } 43 | void build(){ 44 | //fail[i]=2;i--){ 46 | num[fail[i]]+=num[i]; 47 | } 48 | num[0]=num[1]=0; 49 | } 50 | void init(char* ss){ 51 | while (*ss){ 52 | add(*ss-'a');ss++; 53 | } 54 | } 55 | void init(string str){ 56 | for (int i=0;i 5 | #define RIGHT 6 | //RIGHT: parent树的dfs序上主席树,求每个点的Right集合 7 | using namespace std; 8 | const int maxn = 25e4+100; 9 | #ifdef RIGHT 10 | struct Node{int L,R,val;}Tree[maxn*40]; 11 | struct Chairman_Tree{ 12 | int cnt = 0; 13 | int root[maxn*2]; 14 | void init(){ 15 | memset(root,0,sizeof root); 16 | cnt =0; 17 | } 18 | /* 建T0空树 */ 19 | int buildT0(int l, int r){ 20 | int k = cnt++; 21 | Tree[k].val =0; 22 | if (l==r) return k; 23 | int mid = l+r >>1; 24 | Tree[k].L = buildT0(l, mid);Tree[k].R = buildT0(mid + 1, r); 25 | return k; 26 | } 27 | /* 上一个版本节点P,【ppos】+=del 返回新版本节点*/ 28 | int update (int P,int l,int r,int ppos,int del){ 29 | assert(cnt < maxn*50); 30 | int k = cnt++; 31 | Tree[k].val = Tree[P].val +del; 32 | if (l==r) return k; 33 | int mid = l+r >>1; 34 | if (ppos<=mid){ 35 | Tree[k].L = update(Tree[P].L,l,mid,ppos,del); 36 | Tree[k].R = Tree[P].R; 37 | }else{ 38 | Tree[k].L = Tree[P].L; 39 | Tree[k].R = update(Tree[P].R,mid+1,r,ppos,del); 40 | } 41 | return k; 42 | } 43 | int query(int PL,int PR,int l,int r,int L,int R){ 44 | if (l>R || L>r)return 0; 45 | if (L <= l && r <= R)return Tree[PR].val - Tree[PL].val; 46 | int mid = l + r >> 1; 47 | return query(Tree[PL].L,Tree[PR].L,l,mid,L,R) + query(Tree[PL].R,Tree[PR].R,mid+1,r,L,R); 48 | } 49 | }tree; 50 | #endif 51 | char s[maxn];int n,ans[maxn]; 52 | /*注意需要按l将节点基数排序来拓扑更新parent树*/ 53 | struct Suffix_Automaton{ 54 | //basic 55 | int nxt[maxn*2][26],fa[maxn*2],l[maxn*2]; 56 | int last,cnt; 57 | //extension 58 | int cntA[maxn*2],A[maxn*2];/*辅助拓扑更新*/ 59 | int num[maxn*2];/*每个节点代表的所有串的出现次数*/ 60 | #ifdef RIGHT 61 | vector E[maxn*2]; 62 | int dfsl[maxn*2],dfsr[maxn*2],dfn; 63 | int pos[maxn*2]; 64 | int end_pos[maxn*2];//1基 65 | #endif 66 | Suffix_Automaton(){ clear(); } 67 | void clear(){ 68 | last =cnt=1; 69 | fa[1]=l[1]=0; 70 | memset(nxt[1],0,sizeof nxt[1]); 71 | } 72 | void init(char *s){ 73 | while (*s){ 74 | add(*s-'a');s++; 75 | } 76 | } 77 | void add(int c){ 78 | int p = last; 79 | int np = ++cnt; 80 | memset(nxt[cnt],0,sizeof nxt[cnt]); 81 | l[np] = l[p]+1;last = np; 82 | while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p]; 83 | if (!p)fa[np]=1; 84 | else{ 85 | int q = nxt[p][c]; 86 | if (l[q]==l[p]+1)fa[np] =q; 87 | else{ 88 | int nq = ++ cnt; 89 | l[nq] = l[p]+1; 90 | memcpy(nxt[nq],nxt[q],sizeof (nxt[q])); 91 | fa[nq] =fa[q];fa[np] = fa[q] =nq; 92 | while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p]; 93 | } 94 | } 95 | } 96 | void build(){ 97 | memset(cntA,0,sizeof cntA); 98 | memset(num,0,sizeof num); 99 | for (int i=1;i<=cnt;i++)cntA[l[i]]++; 100 | for (int i=1;i<=cnt;i++)cntA[i]+=cntA[i-1]; 101 | for (int i=cnt;i>=1;i--)A[cntA[l[i]]--] =i; 102 | /*更行主串节点*/ 103 | int temp=1; 104 | for (int i=0;i=1;i--){ 109 | //basic 110 | int x = A[i]; 111 | num[fa[x]]+=num[x]; 112 | //special 113 | ans[l[x]] = max(ans[l[x]],num[x]); 114 | } 115 | //special 116 | for (int i=l[last];i>1;i--){ 117 | ans[i-1] = max(ans[i-1],ans[i]); 118 | } 119 | } 120 | 121 | #ifdef RIGHT 122 | int get_right_between(int u,int l,int r){ 123 | return tree.query(tree.root[dfsl[u] - 1],tree.root[dfsr[u]],1,::n,l,r); 124 | } 125 | void dfs(int u){ 126 | dfsl[u] = ++ dfn; 127 | pos[dfn] = u; 128 | for (int v : E[u]){ 129 | dfs(v); 130 | } 131 | dfsr[u] = dfn; 132 | } 133 | void extract_right(){ 134 | int temp = 1; 135 | for (int i=0;i=1;i--){ 158 | printf("num[%d]=%d l[%d]=%d fa[%d]=%d\n",i,num[i],i,l[i],i,fa[i]); 159 | } 160 | } 161 | }sam; 162 | int main(){ 163 | scanf("%s",s); 164 | /* calc n must before sam.init()*/ 165 | n = strlen(s); 166 | sam.init(s); 167 | sam.build(); 168 | for (int i=1;i<=n;i++){ 169 | printf("%d\n",ans[i]); 170 | } 171 | return 0; 172 | } -------------------------------------------------------------------------------- /String/Dictionary_of_Basic_Factors.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 2019/10/28. 2 | // CF 100962D 求区间border series,最大border。 3 | #pragma GCC optimize(3) 4 | #include 5 | #define rank rkrkrk 6 | using namespace std; 7 | const int maxn = 4e5 + 100; 8 | const int maxlog = 19; 9 | struct Sequence{ 10 | /** l + k*d <=r **/ 11 | int l,r,d; 12 | Sequence(int ll = 0,int rr = 0,int dd = 0){ 13 | l = ll;r = rr;d = dd; 14 | } 15 | Sequence(const vector & pos){ 16 | if (pos.empty()){ 17 | l = r = d = 0; 18 | }else if (pos.size() == 1){ 19 | l = pos.front(); 20 | r = pos.front(); 21 | d = 1; 22 | }else{ 23 | l = pos.front(); 24 | r = pos.back(); 25 | d = pos[1] - pos[0]; 26 | } 27 | } 28 | bool has(int x){ 29 | return d and x >= l and x <= r and x % d == l % d; 30 | } 31 | int count(){ 32 | if (d == 0)return 0; 33 | return (r - l) / d + 1; 34 | } 35 | vector to_list(){ 36 | vector list(0); 37 | if (d == 0)return list; 38 | for (int i=l;i<=r;i+=d)list.push_back(i); 39 | return list; 40 | } 41 | }; 42 | Sequence operator -(int X, Sequence S){return Sequence(X - S.r,X - S.l, S.d);} 43 | Sequence operator -(Sequence S, int X){return Sequence(S.l - X, S.r - X, S.d);} 44 | Sequence operator &(Sequence S1, Sequence S2){ 45 | int cnt1 = S1.count(), cnt2 = S2.count(); 46 | if (cnt1 == 0 || cnt2 == 0) return Sequence(0,0,0); 47 | if (cnt1 > cnt2){ 48 | swap(S1,S2);swap(cnt1,cnt2); 49 | } 50 | if (cnt1 < 3){ 51 | vector pos(0); 52 | for (int x : S1.to_list()){ 53 | if (S2.has(x)) pos.push_back(x); 54 | } 55 | return Sequence(pos); 56 | }else{ 57 | if (S1.d == S2.d){ 58 | int l = max(S1.l,S2.l), r = min(S1.r,S2.r); 59 | if (r >= l && S1.l % S1.d == S2.l % S1.d)return Sequence(l,r,S1.d); 60 | else return Sequence(0,0,0); 61 | }else assert(0); 62 | } 63 | } 64 | struct Run{ 65 | //S[l,r] is a run of period of length d. 66 | int l,r,d; 67 | Run(int ll = 0,int rr = 0,int dd = 0){ 68 | l = ll;r = rr;d = dd; 69 | } 70 | bool operator < (const Run &other)const{ 71 | if (l != other.l)return l < other.l; 72 | if (r != other.r)return r < other.r; 73 | if (d != other.d)return d < other.d; 74 | return false; 75 | } 76 | bool operator == (const Run &other)const{ 77 | return l == other.l and r == other.r and d == other.d; 78 | } 79 | }; 80 | struct Dictionary_of_Basic_Factories{ 81 | /** 1-base **/ 82 | int name[maxn][maxlog];int n; 83 | vector > pos[maxlog]; 84 | int cntA[maxn],cntB[maxn],tsa[maxn],A[maxn],B[maxn]; 85 | int sa[maxn],rank[maxn]; 86 | int height[maxn]; 87 | void clear(){ 88 | for (int i=0;i<=max(n,'z' + 10);i++){ 89 | cntA[i] = cntB[i] = tsa[i] = A[i] = B[i] = sa[i] = rank[i] = height[i] = 0; 90 | for (int k=0;kn = n; 96 | for (int i=1;i<=n;i++)cntA[ch[i]]++; 97 | for (int i=1;i=1;i--)sa[cntA[ch[i]]--] = i; 99 | rank[sa[1]] = 1; 100 | for (int i=2;i<=n;i++){ 101 | rank[sa[i]] = rank[sa[i-1]]; 102 | if (ch[sa[i]] != ch[sa[i-1]])rank[sa[i]] ++; 103 | } 104 | pos[0].resize(rank[sa[n]] + 1,vector(0)); 105 | for (int i=1;i<=n;i++){ 106 | name[i][0] = rank[i]; 107 | pos[0][rank[i]].push_back(i); 108 | } 109 | for (int step = 1,l=1;l <= n;l<<=1,step ++){ 110 | for (int i=0;i<=n;i++)cntA[i] = cntB[i] = 0; 111 | for (int i=1;i<=n;i++){ 112 | cntA[A[i] = rank[i]] ++; 113 | cntB[B[i]=(i+l<=n)?rank[i+l]:0]++; 114 | } 115 | for (int i=1;i<=n;i++)cntB[i] += cntB[i-1]; 116 | for (int i=n;i>=1;i--)tsa[cntB[B[i]]--] = i; 117 | for (int i=1;i<=n;i++)cntA[i] += cntA[i-1]; 118 | for (int i=n;i>=1;i--)sa[cntA[A[tsa[i]]]--] = tsa[i]; 119 | rank[sa[1]] = 1; 120 | for (int i=2;i<=n;i++){ 121 | rank[sa[i]] = rank[sa[i-1]]; 122 | if (A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]])rank[sa[i]] ++; 123 | } 124 | pos[step].resize(rank[sa[n]] + 1,vector (0)); 125 | for (int i = 1;i <=n;i++){ 126 | name[i][step] = rank[i]; 127 | pos[step][rank[i]].push_back(i); 128 | } 129 | } 130 | } 131 | void get_height(char *ch, int n){ 132 | 133 | sa[0] = rank[0] = 0; 134 | for (int i=1,j=0;i<=n;i++){ 135 | if (j)j--; 136 | while (ch[i+j] == ch[sa[rank[i]-1] +j])j++; 137 | height[rank[i]]= j; 138 | } 139 | } 140 | // get sequence [2^step,2^(step+1)) 141 | Sequence get_seq(vector & list, int l, int r){ 142 | vector pos(0); 143 | int idx = lower_bound(list.begin(),list.end(),l) - list.begin(); 144 | while (idx < list.size() && pos.size() < 3 && list[idx] <= r){ 145 | pos.push_back(list[idx]);idx ++; 146 | } 147 | if (pos.size() < 3)return Sequence(pos); 148 | else{ 149 | int last = upper_bound(list.begin(),list.end(),r) - list.begin() - 1; 150 | int L = pos.front(), d = pos[1] - pos[0], R = list[last]; 151 | return Sequence(L,R,d); 152 | } 153 | } 154 | Sequence get_border(int l,int r,int step){ 155 | int len = r - l + 1; 156 | int baby = 1 << step, giant = min(len-1,(baby * 2-1)); 157 | int namel = name[l][step], namer = name[r - baby + 1][step]; 158 | Sequence seql = get_seq(pos[step][namel],r - giant + 1,r - baby + 1), 159 | seqr = get_seq(pos[step][namer],l,l + giant - baby); 160 | seql = (r + 1) - seql; seqr = seqr - (l -baby); 161 | return seql & seqr; 162 | } 163 | /** return O(logn) border series of S[l,r]. 164 | * Attention: can contain empty sequence (0,0,0) 165 | * if [2^i,2^(i+1)) border does not exist.*/ 166 | vector get_border_series(int l,int r){ 167 | vector ret(0); 168 | for (int step = 0;(1<=0;k--){ 176 | if ((1<= len)continue; 177 | Sequence seq = get_border(l,r,k); 178 | if (seq.r)return seq.r; 179 | } 180 | return 0; 181 | } 182 | int lcp(int x,int y){ 183 | int len = 0; 184 | for (int k = maxlog-1;k>=0;k--){ 185 | int LEN = 1<< k; 186 | if (x + LEN - 1 <= n and y + LEN - 1 <= n and name[x][k] == name[y][k]){ 187 | len += 1<=0;k--){ 197 | int LEN = 1 << k; 198 | if (x >= LEN and y >= LEN and name[x - LEN + 1][k] == name[y - LEN + 1][k]){ 199 | len += LEN; 200 | x -= LEN; 201 | y -= LEN; 202 | } 203 | } 204 | return len; 205 | } 206 | vector get_all_runs(){ 207 | // cerr< run_list(0); 209 | for (int per = 1; per * 2 <= n; per ++){ 210 | for (int pos = per;pos <= n;pos += per){ 211 | int left = lcs(pos,pos + per); 212 | int right = lcp(pos,pos + per); 213 | if (left + right > per){ 214 | run_list.push_back(Run(pos - left + 1,pos + per + right - 1,per)); 215 | } 216 | } 217 | } 218 | vector result(0); 219 | pair pre = {-1,-1}; 220 | for (auto run : run_list){ 221 | pair now = {run.l,run.r}; 222 | if (pre != now){ 223 | pre = now; 224 | result.push_back(run); 225 | } 226 | } 227 | return result; 228 | } 229 | }dbf; 230 | char s[maxn]; 231 | int n,q; 232 | int main(){ 233 | scanf("%d%d",&n,&q); 234 | scanf("%s",s + 1); 235 | dbf.init(s,n); 236 | while (q--){ 237 | int l,r; 238 | scanf("%d%d",&l,&r); 239 | printf("%d\n",dbf.get_biggest_border(l,r)); 240 | } 241 | return 0; 242 | } -------------------------------------------------------------------------------- /String/EX_KMP.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 2019/12/11. 2 | // CF 1200E 3 | #include 4 | using namespace std; 5 | const int maxn = 1e6 + 100; 6 | //result: extend[i] = LCP(S[i,lens],T) 7 | //require: nxt[i] = LCP(T[i,lent],T) 8 | void exkmp(char *s,int lens,char *t,int lent,int *extend,int *nxt){ 9 | extend[0] = 0; 10 | for (int i = 1,p0 = 0,p = 0;i <= lens;i ++){ 11 | extend[i] = i <= p ? min(nxt[i - p0 + 1], p - i + 1) : 0; 12 | while (i + extend[i] <= lens and extend[i] < lent and s[i + extend[i]] == t[extend[i]+1])extend[i] ++; 13 | if (i + extend[i] - 1 >= p and i != 1)p0 = i,p = i + extend[i] - 1; 14 | } 15 | } 16 | char s[maxn],t[maxn]; 17 | int extend[maxn]; 18 | int nxt[maxn]; 19 | int main(){ 20 | int n; 21 | scanf("%d",&n); 22 | int LEN = 0; 23 | for (int i=1;i<=n;i++){ 24 | scanf("%s",t+1); 25 | int lent = strlen(t+1); 26 | int lens = min(LEN,lent); 27 | exkmp(t,lent,t,lent,nxt,nxt); 28 | exkmp(s + LEN - lens,lens,t,lent,extend,nxt); 29 | int sp = 0; 30 | for (int j = 1;j <= lens;j ++){ 31 | if (lens - j + 1 == extend[j]){ 32 | sp = extend[j]; 33 | break; 34 | } 35 | } 36 | strcpy(s + LEN+1,t + sp + 1); 37 | LEN += lent - sp; 38 | } 39 | printf("%s\n",s+1); 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /String/Hash.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 18-6-1. 2 | // CF 1003F 3 | #include 4 | using namespace std; 5 | typedef unsigned long long ULL; 6 | const int maxn = 305*305; 7 | /* 字符集大小 */ 8 | const int sigma = maxn; 9 | /* hash次数 */ 10 | const int HASH_CNT = 2; 11 | int n; 12 | int s[maxn]; 13 | /* char* 1-bas 14 | * sum[i] = s[i]+s[i-1]*Seed+s[i-2]*Seed^2+...+s[1]*Seed^(i-1)*/ 15 | ULL Prime_Pool[] = {1998585857ul,23333333333ul}; 16 | ULL Seed_Pool[]={911,146527,19260817,91815541}; 17 | ULL Mod_Pool[]={29123,998244353,1000000009,4294967291ull}; 18 | struct Hash{ 19 | ULL Seed,Mod; 20 | ULL bas[maxn];ULL sum[maxn]; 21 | int perm[sigma]; 22 | Hash(ULL Seed, ULL Mod):Seed(Seed), Mod(Mod){ 23 | bas[0] = 1; 24 | for (int i = 1; i <= n; i++){ 25 | bas[i] = bas[i - 1] * Seed % Mod; 26 | } 27 | } 28 | void init(){ 29 | for (int i=1;i<=n;i++){ 30 | sum[i] = (sum[i-1]*Seed%Mod+s[i])%Mod; 31 | } 32 | } 33 | /*random_shuffle 离散化id,防止kill_hash*/ 34 | void indexInit(){ 35 | iota(perm + 1, perm + 1 + sigma, 1); 36 | random_shuffle(perm+1,perm+1+sigma); 37 | for (int i=1;i<=n;i++){ 38 | sum[i] = (sum[i-1]*Seed%Mod+perm[s[i]])%Mod; 39 | } 40 | } 41 | ULL getHash(int l,int r){ 42 | return (sum[r]-sum[l-1]*bas[r-l+1]%Mod+Mod)%Mod; 43 | } 44 | }hasher[HASH_CNT] = {Hash(Seed_Pool[0], Mod_Pool[0]), Hash(Seed_Pool[1], Mod_Pool[1])}; 45 | map,int>,int>veid;int vecnt; 46 | mapid;int idcnt; 47 | vector pos[maxn]; 48 | string a[maxn]; 49 | int sumL[maxn]; 50 | int main(){ 51 | cin>>n; 52 | for (int i=1;i<=n;i++){ 53 | cin>>a[i]; 54 | if (!id[a[i]])id[a[i]] = ++idcnt; 55 | s[i] = id[a[i]]; 56 | sumL[i] = sumL[i-1]+a[i].size(); 57 | } 58 | for (int i=0;i,int> x = {{hash1,hash2},len}; 68 | if (veid[x]==0)veid[x] = ++vecnt; 69 | pos[veid[x]].push_back(i); 70 | } 71 | } 72 | int maxDelta =0; 73 | for (auto x:veid){ 74 | int len = x.first.second; 75 | int i = x.second; 76 | sort(pos[i].begin(),pos[i].end()); 77 | int num =0; 78 | for (int j=0,last = -maxn;j=last+len){ 80 | last = pos[i][j]; 81 | num++; 82 | } 83 | } 84 | if (num==1)continue; 85 | int cost1 = sumL[pos[i][0]+len-1]-sumL[pos[i][0]-1]+len-1; 86 | int cost2 = len; 87 | int tempDelta = (cost1-cost2)*num; 88 | maxDelta = max(maxDelta,tempDelta); 89 | } 90 | cout< 6 | using namespace std; 7 | const int maxn = 1e6+100; 8 | struct KMP{ 9 | int nxt[maxn];int len; 10 | char t[maxn]; 11 | void clear(){ 12 | len =nxt[0] = nxt[1] =0; 13 | } 14 | /* 1-bas */ 15 | /* 注意在ss结尾添加‘\0’ */ 16 | void init(char* ss){ 17 | len = strlen(ss+1); 18 | memcpy(t,ss,(len+2)*sizeof(char)); 19 | for (int i=2;i<=len;i++){ 20 | nxt[i] = nxt[i-1]; 21 | while (nxt[i]&&ss[i]!=ss[nxt[i]+1]) nxt[i] = nxt[nxt[i]]; 22 | nxt[i]+=(ss[i]==ss[nxt[i]+1]); 23 | } 24 | } 25 | /* 求所有在ss串中的start_pos. 如果first_only设置为true,则只返回第一个位置*/ 26 | vector match(char *ss,bool first_only = false){ 27 | int len_s = strlen(ss+1); 28 | vector start_pos(0); 29 | for (int i=1,j=1;i<=len_s;){ 30 | while (j!=1 && ss[i] != t[j])j = nxt[j-1]+1; 31 | if (ss[i] == t[j]) j++,i++; 32 | else i++; 33 | if (j == len+1){ 34 | start_pos.push_back(i-j+1); 35 | if (first_only)return start_pos; 36 | j = nxt[len]+1; 37 | } 38 | } 39 | return start_pos; 40 | } 41 | void debug(){ 42 | for (int i=0;i<=len;i++){ 43 | printf("[debug] nxt[%d]=%d\n",i,nxt[i]); 44 | } 45 | } 46 | /* 循环周期 形如 acaca 中 ac 是一个合法周期 */ 47 | vector periodic(){ 48 | vector ret; 49 | int now = len; 50 | while (now){ 51 | now = nxt[now]; 52 | ret.push_back(len-now); 53 | } 54 | return ret; 55 | } 56 | /* 循环节 形如 acac 中ac、acac是循环节,aca不是*/ 57 | vector periodic_loop(){ 58 | vectorret ; 59 | for (int x :periodic()){ 60 | if (len%x==0)ret.push_back(x); 61 | } 62 | return ret; 63 | } 64 | int min_periodic_loop(){ 65 | return periodic_loop()[0]; 66 | } 67 | }kmper; 68 | vector s; 69 | vector > a,maxVal; 70 | int cnt1[maxn],cnt2[maxn],n,m; 71 | char S[maxn]; 72 | pair pq[maxn];int l,r; 73 | int main(){ 74 | cin>>n>>m; 75 | s.resize(n+1); 76 | maxVal.resize(n+1); 77 | for (int i=1; i<=n;i++){ 78 | cin>>s[i]; 79 | } 80 | a.resize(n+1); 81 | for (int i=1;i<=n;i++){ 82 | a[i].resize(m+1); 83 | maxVal[i].resize(m+1); 84 | for (int j=1;j<=m;j++){ 85 | cin>>a[i][j]; 86 | } 87 | } 88 | int p,q;kmper.clear(); 89 | for (int i=1;i<=n;i++){ 90 | for (int j=1;j<=m;j++){ 91 | S[j] = s[i][j-1]; 92 | } 93 | S[m+1]='\0'; 94 | kmper.init(S); 95 | for (int x:kmper.periodic()){ 96 | cnt1[x]++; 97 | } 98 | } 99 | for (int j=1;j<=m;j++){ 100 | for (int i=1;i<=n;i++){ 101 | S[i] = s[i][j-1]; 102 | } 103 | S[n+1]='\0'; 104 | kmper.init(S); 105 | for (int x:kmper.periodic()){ 106 | cnt2[x]++; 107 | } 108 | } 109 | for (int i=maxn;i>=1;i--){ 110 | if (cnt1[i]==n){ q = i; } 111 | if (cnt2[i]==m){ p=i; } 112 | } 113 | for (int i=1;i<=n;i++){ 114 | l = 0,r=0; 115 | for (int j=1;j<=m;j++){ 116 | while (r>l&&pq[l].second<=j-q)l++; 117 | while (r>l&&pq[r-1].first<=a[i][j])r--; 118 | pq[r++] = {a[i][j],j}; 119 | if (j>=q){ 120 | maxVal[i][j-q+1] = pq[l].first; 121 | } 122 | } 123 | } 124 | int ans = 0x3f3f3f3f; 125 | for (int j=1;j<=m-q+1;j++){ 126 | l=r=0; 127 | for (int i=1;i<=n;i++){ 128 | while (r>l&&pq[l].second<=i-p)l++; 129 | while (r>l&&pq[r-1].first<=maxVal[i][j])r--; 130 | pq[r++] = {maxVal[i][j],i}; 131 | if (i>=p){ 132 | ans = min(ans,pq[l].first); 133 | } 134 | 135 | } 136 | } 137 | cout<<1LL*(p+1)*(q+1)*ans< 3 | using namespace std; 4 | const int MAX = 2e5+10000; 5 | char s[MAX]; 6 | struct Manacher{ 7 | int lc[MAX]; 8 | char ch[MAX]; 9 | int N; 10 | Manacher(char *s){init(s);manacher();} 11 | /* s 1 bas */ 12 | void init(char *s){ 13 | int n = strlen(s+1); 14 | ch[n*2 +1] = '#'; 15 | ch[0] = '@'; 16 | ch[n*2 +2] = '\0'; 17 | for (int i=n;i>=1;i--){ 18 | ch[i*2] = s[i];ch[i*2 -1] = '#'; 19 | } 20 | N = 2* n +1; 21 | } 22 | void manacher(){ 23 | lc[1]=1; int k=1; 24 | for (int i=2;i<=N;i++){ 25 | int p = k+lc[k]-1; 26 | if (i<=p){ 27 | lc[i]=min(lc[2*k-i],p-i+1); 28 | }else{ lc[i]=1; } 29 | while (ch[i+lc[i]]==ch[i-lc[i]])lc[i]++; 30 | if (i+lc[i]>k+lc[k])k=i; 31 | } 32 | } 33 | void debug(){ 34 | puts(ch); 35 | for (int i=1;i<=N;i++){ 36 | printf("lc[%d]=%d\n",i,lc[i]); 37 | } 38 | } 39 | }; 40 | int main(){ 41 | scanf("%s",s+1); 42 | Manacher manacher(s); 43 | manacher.debug(); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /String/Palindrome_Series.cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 19-11-20. 2 | // CF 932G 偶回文分割方案数 3 | // 优化DP转移:枚举所有回文后缀转移 4 | // 使用时,只需要修改3行TBD 5 | #include 6 | using namespace std; 7 | const int mod = 1e9 + 7; 8 | const int maxn = 1e6+100; 9 | struct Palindromic_AutoMaton{ 10 | int s[maxn],now; 11 | int nxt[maxn][26],fail[maxn],l[maxn],last,tot; 12 | int diff[maxn],anc[maxn],g[maxn],f[maxn]; 13 | void clear(){ 14 | //1节点:奇数长度root 0节点:偶数长度root 15 | s[0] = l[1] = -1; 16 | fail[0] = tot = now =1; 17 | last = l[0] = 0; 18 | memset(nxt[0],0,sizeof nxt[0]); 19 | memset(nxt[1],0,sizeof nxt[1]); 20 | } 21 | Palindromic_AutoMaton(){clear();} 22 | int newnode(int len){ 23 | tot++; 24 | memset(nxt[tot],0,sizeof nxt[tot]); 25 | fail[tot]=0;l[tot]=len; 26 | return tot; 27 | } 28 | int get_fail(int x){ 29 | while (s[now-l[x]-2]!=s[now-1])x = fail[x]; 30 | return x; 31 | } 32 | void add(int ch){ 33 | s[now++] = ch; 34 | int cur = get_fail(last); 35 | if(!nxt[cur][ch]){ 36 | int tt = newnode(l[cur]+2); 37 | fail[tt] = nxt[get_fail(fail[cur])][ch]; 38 | nxt[cur][ch] = tt; 39 | diff[tt] = l[tt] - l[fail[tt]]; 40 | anc[tt] = diff[tt] == diff[fail[tt]]? anc[fail[tt]] : fail[tt]; 41 | } 42 | last = nxt[cur][ch]; 43 | } 44 | void trans(int i){ 45 | for (int p = last;p>1;p = anc[p]){ 46 | g[p] = f[i - l[anc[p]] - diff[p]];/*TBD*/ 47 | if (diff[p] == diff[fail[p]]){ 48 | (g[p] += g[fail[p]]) %= mod;/*TBD*/ 49 | } 50 | (f[i] += (i % 2 == 0) *g[p]) %= mod;/*TBD*/ 51 | } 52 | } 53 | int init(char* s){ 54 | f[0] = 1; 55 | int n = strlen(s + 1); 56 | for (int i=1;i<=n;i++){ 57 | add(s[i] - 'a'); 58 | trans(i); 59 | } 60 | return f[n]; 61 | } 62 | }pam; 63 | char t[maxn], s[maxn]; 64 | int main(){ 65 | scanf("%s",s + 1); 66 | int n = strlen(s+1); 67 | for (int i=1;i<=n/2;i++){ 68 | t[2 * i - 1] = s[i]; 69 | t[2 * i] = s[n + 1- i ]; 70 | } 71 | cout< 7 | #define rank rkrkrk 8 | //#define _DEBUG 9 | #define RMQ 10 | using namespace std; 11 | const int maxn = 3e5+100; 12 | int w[maxn]; 13 | int lg[maxn]; 14 | struct Run{ 15 | int l,r,k; 16 | }; 17 | struct UFS { 18 | int fa[maxn]; 19 | void init(int n) { iota(fa, fa + n + 1, 0); } 20 | int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } 21 | bool unite(int u, int v) { 22 | u = find(u); v = find(v); 23 | fa[u] = v; 24 | return u != v; 25 | } 26 | } ufs[20]; 27 | 28 | int unite(int u, int v, int k) { 29 | if (ufs[k].unite(u, v)) { 30 | if (k == 0) return 1; 31 | return unite(u, v, k - 1) + unite(u + (1<<(k-1)), v + (1<<(k-1)), k - 1); 32 | } else return 0; 33 | } 34 | 35 | long long merge(int u, int v, int l) { 36 | int k = log2(l); 37 | int ret = unite(u, v, k) + 38 | unite(u + l - (1<>1; 54 | build(x<<1,l,mid,h); 55 | build(x<<1|1,mid+1,r,h); 56 | up(x); 57 | } 58 | int query(int x,int l,int r,int L,int R){ 59 | if (l > R || L > r)return 0x3f3f3f3f; 60 | if (L<= l && r <= R)return min_val[x]; 61 | int mid = l + r >> 1; 62 | return min(query(x<<1,l,mid,L,R),query(x<<1|1,mid+1,r,L,R)); 63 | } 64 | }segtree; 65 | #else 66 | int st[maxn][20]; 67 | void st_init(int n,int*h){ 68 | for (int i=1;i<=n;i++){ 69 | st[i][0] = h[i]; 70 | } 71 | for (int j=1;(1<=1;i--)sa[cntA[ch[i]]--] = i; 86 | rank[sa[1]] = 1; 87 | for (int i=2;i<=n;i++){ 88 | rank[sa[i]] = rank[sa[i-1]]; 89 | if (ch[sa[i]] != ch[sa[i-1]])rank[sa[i]] ++; 90 | } 91 | for (int l=1;rank[sa[n]]=1;i--)tsa[cntB[B[i]]--] = i; 99 | for (int i=1;i<=n;i++)cntA[i] += cntA[i-1]; 100 | for (int i=n;i>=1;i--)sa[cntA[A[tsa[i]]]--] = tsa[i]; 101 | rank[sa[1]] = 1; 102 | for (int i=2;i<=n;i++){ 103 | rank[sa[i]] = rank[sa[i-1]]; 104 | if (A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]])rank[sa[i]] ++; 105 | } 106 | } 107 | } 108 | void get_height(int *ch,int n){ 109 | get_sa(ch,n); 110 | sa[0] = rank[0] = 0; 111 | for (int i=1,j=0;i<=n;i++){ 112 | if (j) j--; 113 | while (ch[i+j] == ch[sa[rank[i]-1]+j])j++; 114 | height[rank[i]] = j; 115 | } 116 | #ifdef _DEBUG 117 | for (int i=1;i<=n;i++){ 118 | printf("height[%d]=%d\n",i,height[i]); 119 | } 120 | #endif 121 | #ifndef RMQ 122 | segtree.build(1,1,n,height); 123 | #else 124 | st_init(n,height); 125 | #endif 126 | } 127 | int get_lcp(int x,int y,int n){ 128 | int rkx = rank[x]; 129 | int rky = rank[y]; 130 | if (rkx>rky)swap(rkx,rky); 131 | rkx++; 132 | #ifndef RMQ 133 | int lcp = segtree.query(1,1,n,rkx,rky); 134 | #else 135 | int k = lg[(rky - rkx+1)]; 136 | int lcp = min(st[rkx][k],st[rky - (1< get_run(int*ch,int n){ 147 | sa1.get_height(ch,n); 148 | for (int i=0;i<=n+1;i++){ 149 | ch2[i] = ch[i]; 150 | } 151 | reverse(ch2+1,ch2+1+n); 152 | sa2.get_height(ch2,n); 153 | vector result(0); 154 | int len_max = n/2; 155 | for (int len = 1;len <=len_max;len ++){ 156 | //get_len_run 157 | for (int i=1;i<=n;i+=len){ 158 | int j = i+len; 159 | if (j >n)break; 160 | int lcp = sa1.get_lcp(i,j,n); 161 | int lcs = sa2.get_lcp(n+1-i,n+1-j,n); 162 | lcp = min(lcp,len); 163 | lcs = min(lcs,len); 164 | assert(j+lcp-1<=n); 165 | assert(i-lcs+1>=1); 166 | #ifdef _DEBUG 167 | printf("i=%d,j=%d,len=%d,lcp=%d,lcs=%d\n",i,j,len,lcp,lcs); 168 | #endif 169 | if (lcp + lcs - 1 < len)continue; 170 | int L = j-lcs+1; 171 | int R = j + lcp -1; 172 | result.push_back((Run){L,R,len}); 173 | } 174 | } 175 | #ifdef _DEBUG 176 | for (Run run : result){ 177 | printf("[run]: l=%d, r=%d,k=%d\n",run.l,run.r,run.k); 178 | } 179 | #endif 180 | return result; 181 | } 182 | int n; 183 | typedef long long ll; 184 | ll spanning_forest(vector &runs){ 185 | sort(runs.begin(),runs.end(),[](Run x,Run y){ 186 | return w[x.k] < w[y.k]; 187 | }); 188 | ll ans = 0; 189 | for (auto& R : runs) { 190 | int l = R.l, r = R.r; 191 | ans += 1ll * merge(l - R.k, l, r - l + 1) * w[R.k]; 192 | } 193 | return ans; 194 | } 195 | int ch[maxn]; 196 | int main(){ 197 | for (int i=2;i all_run = get_run(ch,n); 213 | printf("%lld\n",spanning_forest(all_run)); 214 | } 215 | return 0; 216 | } 217 | -------------------------------------------------------------------------------- /String/Trie-Graph(SegmentTree).cpp: -------------------------------------------------------------------------------- 1 | // Created by calabash_boy on 2019/10/27. 2 | #include 3 | using namespace std; 4 | const int maxn = 2e5 + 100; 5 | int n; 6 | int p[maxn], c[maxn]; 7 | struct Node{ 8 | int lson,rson; 9 | int val; 10 | void init(){ 11 | val = 0; 12 | lson = rson = -1; 13 | } 14 | }nodes[maxn * 25]; 15 | int node_cnt = 1; 16 | int build(int x,int l,int r){ 17 | int now = node_cnt ++; 18 | nodes[now].init(); 19 | if (l == r) return now; 20 | int mid = l + r >> 1; 21 | nodes[now].lson = build(x<<1,l,mid); 22 | nodes[now].rson = build(x<<1|1,mid+1,r); 23 | return now; 24 | } 25 | int update(int id,int l,int r,int pos,int val){ 26 | int now = node_cnt ++; 27 | nodes[now] = nodes[id]; 28 | if (l == r){ 29 | nodes[now].val = val; 30 | return now; 31 | } 32 | int mid = l + r >> 1; 33 | if (pos <= mid)nodes[now].lson = update(nodes[id].lson,l,mid,pos,val); 34 | else nodes[now].rson = update(nodes[id].rson,mid+1,r,pos,val); 35 | return now; 36 | } 37 | int query(int id,int l,int r,int pos){ 38 | if (l == r)return nodes[id].val; 39 | int mid = l + r >> 1; 40 | if (pos <= mid)return query(nodes[id].lson,l,mid,pos); 41 | else return query(nodes[id].rson,mid+1,r,pos); 42 | } 43 | struct Trie{ 44 | map nxt[maxn]; 45 | int root[maxn], fail[maxn]; 46 | int cnt = 1; 47 | int insert(int pre,int ch) { 48 | return nxt[pre].find(ch) == nxt[pre].end() ? nxt[pre][ch] = cnt++ : nxt[pre][ch]; 49 | } 50 | void build(){ 51 | queue Q;Q.push(0); 52 | root[0] = ::build(1,1,n); 53 | for (auto edge : nxt[0]){ 54 | int v,ch; 55 | tie(ch,v) = edge; 56 | root[0] = update(root[0],1,n,ch,v); 57 | } 58 | while (!Q.empty()){ 59 | int head = Q.front();Q.pop(); 60 | for (auto edge: nxt[head]){ 61 | int v,ch; 62 | tie(ch,v) = edge; 63 | if (head == 0)fail[v] = 0; 64 | else fail[v] = query(root[fail[head]],1,n,ch); 65 | root[v] = root[fail[v]]; 66 | for (auto edge2 : nxt[v]){ 67 | int v2,ch2; 68 | tie(ch2,v2) = edge2; 69 | root[v] = update(root[v],1,n,ch2,v2); 70 | } 71 | Q.push(v); 72 | } 73 | } 74 | } 75 | }trie; 76 | int main(){ 77 | cin>>n; 78 | for (int i=1;i<=n;i++){ 79 | scanf("%d",p+i); 80 | } 81 | for (int i=1;i<=n;i++){ 82 | scanf("%d",c+i); 83 | trie.insert(p[i],c[i]); 84 | } 85 | trie.build(); 86 | for (int i=1;i<=n;i++){ 87 | cout< 3 | using namespace std; 4 | const int maxn = 2e5 + 100; 5 | struct Trie { 6 | int nxt[maxn][26], fail[maxn]; 7 | // the node I should go when append a character 8 | int Go[maxn][26]; 9 | int root = 0; 10 | int cnt = 0; 11 | void clear(){ 12 | root = cnt = 0; 13 | memset(nxt[0],0,sizeof nxt[0]); 14 | } 15 | int newnode() { 16 | cnt++; 17 | //clear memory 18 | return cnt; 19 | } 20 | void insert(char *s) { 21 | int now = root; 22 | while (*s){ 23 | now = insert(now,*s - 'a'); 24 | s ++; 25 | } 26 | } 27 | int insert(int pre, int ch) { 28 | return nxt[pre][ch]?nxt[pre][ch] : nxt[pre][ch] = newnode(); 29 | } 30 | void build() { 31 | queue Q; 32 | Q.push(0); 33 | memcpy(Go[0],nxt[0],sizeof nxt[0]); 34 | while (!Q.empty()) { 35 | int head = Q.front(); 36 | Q.pop(); 37 | for (int ch = 0; ch < 26; ch++) { 38 | int v = nxt[head][ch]; 39 | if (!v)continue; 40 | if (head == 0) fail[v] = 0; 41 | else fail[v] = Go[fail[head]][ch]; 42 | memcpy(Go[v],Go[fail[v]],sizeof Go[v]); 43 | for (int cc = 0; cc < 26; cc++) { 44 | if (nxt[v][cc])Go[v][cc] = nxt[v][cc]; 45 | } 46 | Q.push(v); 47 | } 48 | } 49 | } 50 | }trie; 51 | --------------------------------------------------------------------------------