NOI2018同步赛体验记

啥都不会的选手只会暴力。

Day1得分是25+44+56。

Day2 $LOJ$上的得分是85+30+25。

加上50分笔试分。差银牌线7分。

「NOI2018」归程

25分做法:求出最短路后直接可持久化并查集维护。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf = 0x7fffffff;
#define Rep(i,a,b) for(register int i=(a);i<=int(b);++i)
#define Dep(i,a,b) for(register int i=(a);i>=int(b);--i)
#define rep(i,a,b) for(register int i=(a);i<int(b);++i)
#define mem(x,v) memset(x,v,sizeof(x))
#define pc putchar
#define gc getchar
#define fi first
#define se second
#define debug(x) cout << #x" = " << x << endl;
#define pp(x,y) cout << "pp: " << x << " " << y << endl;
#define rank __RANK
inline ll read(){
register ll x=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc())if(c=='-')f=-1;
for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
#define rd read
double readdb(){
double x=0,p=0.1;char f=0,c=gc();
for(;!isdigit(c);c=gc())f|=(c=='-');
for(;isdigit(c);c=gc())x=x*10+(c^48);
if(c=='.')for(c=gc();isdigit(c);c=gc(),p/=10)x=x+(c^48)*p;
return f?-x:x;
}
#define rdb() readdb()
void write(ll x){if(x<0)x=-x,pc('-');if(x>=10)write(x/10);putchar(x%10+'0');}
void writeln(ll x){write(x);puts("");}
const int maxn = 2e5+233;
const int maxm = 4e5+233;
int n,m,ans,root[maxn];
#define mid ((l+r)>>1)
#define min(x,y) (x) < (y) ? (x) : (y)
int tot;
struct node{
int fa,rank,lson,rson,mn;
node(){}
bool operator == (const node &w){
return fa == w.fa;
}
bool operator != (const node &w){
return fa != w.fa;
}
}t[maxm*40];
int dist[maxn];bool vis[maxn];
inline void build(int &o,int l,int r){
o = ++tot;
if (l==r){
t[o] . rank = 1;
t[o] . fa = l;
t[o] . mn = dist[l];
return ;
}
t[o] . lson = t[o] . rson = 0;
build(t[o].lson,l,mid);
build(t[o].rson,mid+1,r);
}

inline void add(int &o,int l,int r,int x,int mn,int wzp){
++tot;
t[tot] = t[o];
o = tot;
if (l==r){
t[o] . rank = t[o] . rank + wzp;
t[o] . mn = min(t[o].mn,mn);
return ;
}
if (x <= mid) add(t[o].lson,l,mid,x,mn,wzp); else
add(t[o].rson,mid+1,r,x,mn,wzp);
}

inline void update(int &o,int l,int r,int x,int fa){
++tot;
t[tot] = t[o];
o = tot;
if (l==r){
t[o] . fa = fa;
return ;
}
if (x<=mid) update(t[o].lson,l,mid,x,fa); else
update(t[o].rson,mid+1,r,x,fa);
}

inline node query(int o,int l,int r,int x){
if (l==r) return t[o];
if (x<=mid) return query(t[o].lson,l,mid,x); else
return query(t[o].rson,mid+1,r,x);
}

inline node find(int root,int x){
node tmp = query(root,1,n,x);
if (tmp.fa == x) return tmp;
return find(root,tmp.fa);
}

void merge(int &rt,node x,node y){
if(x.rank > y.rank) swap(x,y);
update(rt,1,n,x.fa,y.fa);//puts("");
add(rt,1,n,y.fa,x.mn,x.rank==y.rank);
}

struct Edge{
int to,nxt,dist;
Edge(){}
Edge(int to,int nxt,int dist):
to(to),nxt(nxt),dist(dist){}
}edge[maxm * 5];
int first[maxn],nume;
void Addedge(int a,int b,int c){
edge[nume] = Edge(b,first[a],c);
first[a] = nume++;
edge[nume] = Edge(a,first[b],c);
first[b] = nume++;
}

priority_queue<pair<int,int> > Q;
#define Mk make_pair
inline void dijkstra(int S){
Rep(i,1,n) dist[i] = inf,vis[i] = false;
Q.push(Mk(-0,S));dist[S] = 0;
while(!Q.empty()){
int u = Q.top().second;Q.pop();
if(vis[u]) continue;
vis[u] = true;
for(int e=first[u];~e;e=edge[e].nxt){
int v = edge[e].to;
if(dist[v] > dist[u] + edge[e].dist){
dist[v] = dist[u] + edge[e].dist;
Q.push(Mk(-dist[v],v));
}
}
}
}
struct A{
int u,v,l,a;
bool operator < (const A&w) const{
return a < w.a;
}
}a[maxm];
int y[maxn];
inline void init(){
n = rd(),m = rd();
nume = 0;
Rep(i,1,n) first[i] = -1;
Rep(i,1,m){
a[i].u = rd(),a[i].v = rd(),a[i].l = rd(),a[i].a = rd();
Addedge(a[i].u,a[i].v,a[i].l);
y[++*y] = a[i].a;
}
dijkstra(1);
sort(y+1,y+1+*y);
*y = unique(y+1,y+1+*y) - y - 1;
Rep(i,1,m) a[i].a = lower_bound(y+1,y+1+*y,a[i].a) - y;
Rep(i,1,m){
a[i] . a = *y - a[i].a + 1;
}
sort(a+1,a+1+m);
root[0] = 0;
tot = 0;
build(root[0],1,n);
for(int i=1,j=1;i<=m;i=j+1){
for(j=i;j<=m && a[i].a==a[j+1].a;++j);
root[a[i].a] = root[a[i].a-1];
Rep(k,i,j){
node x = find(root[a[k].a],a[k].u);
node y = find(root[a[k].a],a[k].v);
if(x != y) merge(root[a[k].a],x,y);
}
}
}
inline void solve(){
init();
int Q = rd(),K = rd(),S = rd(),lastans = 0;
while(Q--){
int v0=rd(),p0=rd();
int v = (v0 + K * lastans - 1) % n + 1;
int p = (p0 + K * lastans) % (S+1);
p = upper_bound(y+1,y+1+*y,p) - y - 1;
p= *y - p;
//找到可能的那个p
node tmp = find(root[p],v);
writeln(lastans = tmp . mn);
}
}

int main(){
freopen("return.in","r",stdin);
freopen("return.out","w",stdout);
int T = rd();
while(T--) solve();
return 0;
}

100分做法:初始化离散化数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf = 0x7fffffff;
#define Rep(i,a,b) for(register int i=(a);i<=int(b);++i)
#define Dep(i,a,b) for(register int i=(a);i>=int(b);--i)
#define rep(i,a,b) for(register int i=(a);i<int(b);++i)
#define mem(x,v) memset(x,v,sizeof(x))
#define pc putchar
#define gc getchar
#define fi first
#define se second
#define debug(x) cout << #x" = " << x << endl;
#define pp(x,y) cout << "pp: " << x << " " << y << endl;
#define rank __RANK
inline ll read(){
register ll x=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc())if(c=='-')f=-1;
for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
#define rd read
double readdb(){
double x=0,p=0.1;char f=0,c=gc();
for(;!isdigit(c);c=gc())f|=(c=='-');
for(;isdigit(c);c=gc())x=x*10+(c^48);
if(c=='.')for(c=gc();isdigit(c);c=gc(),p/=10)x=x+(c^48)*p;
return f?-x:x;
}
#define rdb() readdb()
void write(ll x){if(x<0)x=-x,pc('-');if(x>=10)write(x/10);putchar(x%10+'0');}
void writeln(ll x){write(x);puts("");}
const int maxn = 4e5+233;
const int maxm = 4e5+233;
int n,m,ans,root[maxn];
#define mid ((l+r)>>1)
#define min(x,y) (x) < (y) ? (x) : (y)
int tot;
struct node{
int fa,rank,lson,rson,mn;
node(){}
bool operator == (const node &w){
return fa == w.fa;
}
bool operator != (const node &w){
return fa != w.fa;
}
}t[maxm*40];
int dist[maxn];bool vis[maxn];
inline void build(int &o,int l,int r){
o = ++tot;
if (l==r){
t[o] . rank = 1;
t[o] . fa = l;
t[o] . mn = dist[l];
return ;
}
t[o] . lson = t[o] . rson = 0;
build(t[o].lson,l,mid);
build(t[o].rson,mid+1,r);
}

inline void add(int &o,int l,int r,int x,int mn,int wzp){
++tot;
t[tot] = t[o];
o = tot;
if (l==r){
t[o] . rank = t[o] . rank + wzp;
t[o] . mn = min(t[o].mn,mn);
return ;
}
if (x <= mid) add(t[o].lson,l,mid,x,mn,wzp); else
add(t[o].rson,mid+1,r,x,mn,wzp);
}

inline void update(int &o,int l,int r,int x,int fa){
++tot;
t[tot] = t[o];
o = tot;
if (l==r){
t[o] . fa = fa;
return ;
}
if (x<=mid) update(t[o].lson,l,mid,x,fa); else
update(t[o].rson,mid+1,r,x,fa);
}

inline node query(int o,int l,int r,int x){
if (l==r) return t[o];
if (x<=mid) return query(t[o].lson,l,mid,x); else
return query(t[o].rson,mid+1,r,x);
}

inline node find(int root,int x){
node tmp = query(root,1,n,x);
if (tmp.fa == x) return tmp;
return find(root,tmp.fa);
}

void merge(int &rt,node x,node y){
if(x.rank > y.rank) swap(x,y);
update(rt,1,n,x.fa,y.fa);//puts("");
add(rt,1,n,y.fa,x.mn,x.rank==y.rank);
}

struct Edge{
int to,nxt,dist;
Edge(){}
Edge(int to,int nxt,int dist):
to(to),nxt(nxt),dist(dist){}
}edge[maxm * 5];
int first[maxn],nume;
void Addedge(int a,int b,int c){
edge[nume] = Edge(b,first[a],c);
first[a] = nume++;
edge[nume] = Edge(a,first[b],c);
first[b] = nume++;
}

priority_queue<pair<int,int> > Q;
#define Mk make_pair
inline void dijkstra(int S){
Rep(i,1,n) dist[i] = inf,vis[i] = false;
Q.push(Mk(-0,S));dist[S] = 0;
while(!Q.empty()){
int u = Q.top().second;Q.pop();
if(vis[u]) continue;
vis[u] = true;
for(int e=first[u];~e;e=edge[e].nxt){
int v = edge[e].to;
if(dist[v] > dist[u] + edge[e].dist){
dist[v] = dist[u] + edge[e].dist;
Q.push(Mk(-dist[v],v));
}
}
}
}
struct A{
int u,v,l,a;
bool operator < (const A&w) const{
return a < w.a;
}
}a[maxm];
int y[maxn];
inline void init(){
n = rd(),m = rd();
nume = 0;*y = 0;
Rep(i,1,n) first[i] = -1;
Rep(i,1,m){
a[i].u = rd(),a[i].v = rd(),a[i].l = rd(),a[i].a = rd();
Addedge(a[i].u,a[i].v,a[i].l);
y[++*y] = a[i].a;
}
dijkstra(1);
sort(y+1,y+1+*y);
*y = unique(y+1,y+1+*y) - y - 1;
Rep(i,1,m) a[i].a = lower_bound(y+1,y+1+*y,a[i].a) - y;
Rep(i,1,m){
a[i] . a = *y - a[i].a + 1;
}
sort(a+1,a+1+m);
root[0] = 0;
tot = 0;
build(root[0],1,n);
for(int i=1,j=1;i<=m;i=j+1){
for(j=i;j<=m && a[i].a==a[j+1].a;++j);
root[a[i].a] = root[a[i].a-1];
Rep(k,i,j){
node x = find(root[a[k].a],a[k].u);
node y = find(root[a[k].a],a[k].v);
if(x != y) merge(root[a[k].a],x,y);
}
}
}
inline void solve(){
init();
int Q = rd(),K = rd(),S = rd(),lastans = 0;
while(Q--){
int v0=rd(),p0=rd();
int v = (v0 + K * lastans - 1) % n + 1;
int p = (p0 + K * lastans) % (S+1);
p = upper_bound(y+1,y+1+*y,p) - y - 1;
p= *y - p;
//找到可能的那个p
node tmp = find(root[p],v);
writeln(lastans = tmp . mn);
}
}

int main(){
freopen("return.in","r",stdin);
freopen("return.out","w",stdout);
int T = rd();
while(T--) solve();
return 0;
}

「NOI2018」你的名字

68分做法

​ 建出广义后缀自动机。

​ 求出最后出现位置,暴力跳后缀链接。

​ 时间复杂度$O(n \sqrt n)$

​ 常数很小。

56分做法:

​ 把前面直接维护的东西改成线段树合并爆right集合,并判断。(搏一搏单车变空气)

​ 时间复杂度$O(n \sqrt n log (n))$

​ 常数很小。但还是要5~6s。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf = 0x7fffffff;
#define Rep(i,a,b) for(register int i=(a);i<=int(b);++i)
#define Dep(i,a,b) for(register int i=(a);i>=int(b);--i)
#define rep(i,a,b) for(register int i=(a);i<int(b);++i)
#define mem(x,v) memset(x,v,sizeof(x))
#define pc putchar
#define gc getchar
#define fi first
#define se second
#define debug(x) cout << #x" = " << x << endl;
#define pp(x,y) cout << "pp: " << x << " " << y << endl;
#define rank __RANK
inline ll read(){
register ll x=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc())if(c=='-')f=-1;
for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
#define rd read
void write(ll x){if(x<0)x=-x,pc('-');if(x>=10)write(x/10);putchar(x%10+'0');}
void writeln(ll x){write(x);puts("");}
const int maxn = 2e6+233;
bool sub[maxn];
vector<int> V[maxn];
char s[maxn],t[maxn];
int n;
bool vis[maxn];
int st[maxn],top,l[maxn],r[maxn],root[maxn];
#define mid ((l+r)>>1)
int lc[maxn*40],rc[maxn*40],tot=0,N;
inline int merge(int x,int y){
if(!x || !y) return x|y;
int now = ++tot;
lc[now] = merge(lc[x],lc[y]);
rc[now] = merge(rc[x],rc[y]);
return now;
}

inline void modify(int &o,int l,int r,int x){
if(!o) o = ++tot;
if(l==r) return ;
if(x <= mid) modify(lc[o],l,mid,x); else
modify(rc[o],mid+1,r,x);
}

inline int query(int o,int l,int r,int x,int y){
if(!o) return false;
if(l==r) return l;
if(y<=mid) return query(lc[o],l,mid,x,y); else
if(mid+1<=x) return query(rc[o],mid+1,r,x,y); else{
int x = query(rc[o],mid+1,r,mid+1,y);
if(x) return x;
return query(lc[o],l,mid,x,mid);
}
}

struct SuffixAutomaton{
struct node{
int nxt[26],link,max;
}T[maxn];
int start,last;
int tot;
SuffixAutomaton(){
tot = 0;
start = last = newnode(0);
}
int newnode(int max){
int x = ++tot;
T[x] . max = max;
mem(T[x].nxt,0);
T[x] . link = 0;
return x;
}
inline int extend(int c,int flag){
int u = newnode(T[last] . max + 1),v = last;
if(flag != -1){
modify(root[u],1,N,flag);
}
for(;v && !T[v].nxt[c];v = T[v].link)
T[v].nxt[c] = u;
if(!v){
T[u] . link = start;
} else
if(T[T[v].nxt[c]].max == T[v].max + 1){
T[u].link = T[v].nxt[c];
} else{
int n = newnode(T[v].max+1),o = T[v].nxt[c];
rep(k,0,26) T[n].nxt[k] = T[o].nxt[k];
T[n] . link = T[o].link;
T[o].link = T[u].link = n;
for(;v && T[v].nxt[c] == o;v=T[v].link)
T[v].nxt[c] = n;
}
return last = u;
}
vector<int> V[maxn];
inline void dfs(int u){
for(unsigned i=0;i<V[u].size();++i){
int v = V[u][i];
dfs(v);
root[u] = merge(root[u],root[v]);
}
}
inline void topsort(){
Rep(i,2,tot)
V[T[i].link] . push_back(int(i));
dfs(1);
}
}sam;
int main(){
freopen("name.in","r",stdin);
freopen("name.out","w",stdout);
scanf("%s",s);N = strlen(s);
for(int i=0;s[i];++i) sam.extend(s[i] - 'a',i+1);
n = rd();
Rep(i,1,n){
scanf("%s",t);
sam.last = sam.start;
for(int j=0;t[j];++j){
V[i].push_back(sam.extend(t[j] - 'a',-1));
}
l[i] = rd(),r[i] = rd();
}
sam.topsort();
mem(vis,false);
vis[1] = true;
Rep(i,1,n){
register ll ans = 0;
top = 0;
for(register unsigned j=0;j<V[i].size();++j){
register int x = V[i][j];
for(;!vis[x];x = sam.T[x].link){
st[++top] = x;
vis[x] = true;
register int X = query(root[x],1,N,l[i],r[i]);
if(!X){
ans += sam.T[x].max - sam.T[sam.T[x].link].max;
} else{
int len = X - l[i] + 1;
//长度在1..len都不行
ans += max(0,sam.T[x].max - max(sam.T[sam.T[x].link].max,len));
}
}
}
for(;top;top--) vis[st[top]] = false;
writeln(ans);
}
return 0;
}

100分做法:
加一句如果已经找到直接break的优化……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf = 0x7fffffff;
#define Rep(i,a,b) for(register int i=(a);i<=int(b);++i)
#define Dep(i,a,b) for(register int i=(a);i>=int(b);--i)
#define rep(i,a,b) for(register int i=(a);i<int(b);++i)
#define mem(x,v) memset(x,v,sizeof(x))
#define pc putchar
#define gc getchar
#define fi first
#define se second
#define debug(x) cout << #x" = " << x << endl;
#define pp(x,y) cout << "pp: " << x << " " << y << endl;
#define rank __RANK
inline ll read(){
register ll x=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc())if(c=='-')f=-1;
for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
#define rd read
void write(ll x){if(x<0)x=-x,pc('-');if(x>=10)write(x/10);putchar(x%10+'0');}
void writeln(ll x){write(x);puts("");}
const int maxn = 2e6+233;
bool sub[maxn];
vector<int> V[maxn];
char s[maxn],t[maxn];
int n;
bool vis[maxn];
int st[maxn],top,l[maxn],r[maxn],root[maxn];
#define mid ((l+r)>>1)
int lc[maxn*40],rc[maxn*40],tot=0,N;
inline int merge(int x,int y){
if(!x || !y) return x|y;
int now = ++tot;
lc[now] = merge(lc[x],lc[y]);
rc[now] = merge(rc[x],rc[y]);
return now;
}

inline void modify(int &o,int l,int r,int x){
if(!o) o = ++tot;
if(l==r) return ;
if(x <= mid) modify(lc[o],l,mid,x); else
modify(rc[o],mid+1,r,x);
}

inline int query(int o,int l,int r,int x,int y){
if(!o) return false;
if(l==r) return l;
if(y<=mid) return query(lc[o],l,mid,x,y); else
if(mid+1<=x) return query(rc[o],mid+1,r,x,y); else{
int x = query(rc[o],mid+1,r,mid+1,y);
if(x) return x;
return query(lc[o],l,mid,x,mid);
}
}

struct SuffixAutomaton{
struct node{
int nxt[26],link,max;
}T[maxn];
int start,last;
int tot;
SuffixAutomaton(){
tot = 0;
start = last = newnode(0);
}
int newnode(int max){
int x = ++tot;
T[x] . max = max;
mem(T[x].nxt,0);
T[x] . link = 0;
return x;
}
inline int extend(int c,int flag){
int u = newnode(T[last] . max + 1),v = last;
if(flag != -1){
modify(root[u],1,N,flag);
}
for(;v && !T[v].nxt[c];v = T[v].link)
T[v].nxt[c] = u;
if(!v){
T[u] . link = start;
} else
if(T[T[v].nxt[c]].max == T[v].max + 1){
T[u].link = T[v].nxt[c];
} else{
int n = newnode(T[v].max+1),o = T[v].nxt[c];
rep(k,0,26) T[n].nxt[k] = T[o].nxt[k];
T[n] . link = T[o].link;
T[o].link = T[u].link = n;
for(;v && T[v].nxt[c] == o;v=T[v].link)
T[v].nxt[c] = n;
}
return last = u;
}
vector<int> V[maxn];
inline void dfs(int u){
for(unsigned i=0;i<V[u].size();++i){
int v = V[u][i];
dfs(v);
root[u] = merge(root[u],root[v]);
}
}
inline void topsort(){
Rep(i,2,tot)
V[T[i].link] . push_back(int(i));
dfs(1);
}
}sam;
int main(){
freopen("name.in","r",stdin);
freopen("name.out","w",stdout);
scanf("%s",s);N = strlen(s);
for(int i=0;s[i];++i) sam.extend(s[i] - 'a',i+1);
n = rd();
Rep(i,1,n){
scanf("%s",t);
sam.last = sam.start;
for(int j=0;t[j];++j){
V[i].push_back(sam.extend(t[j] - 'a',-1));
}
l[i] = rd(),r[i] = rd();
}
sam.topsort();
mem(vis,false);
vis[1] = true;
Rep(i,1,n){
register ll ans = 0;
top = 0;
for(register unsigned j=0;j<V[i].size();++j){
register int x = V[i][j];
for(;!vis[x];x = sam.T[x].link){
st[++top] = x;
vis[x] = true;
register int X = query(root[x],1,N,l[i],r[i]);
if(!X){
ans += sam.T[x].max - sam.T[sam.T[x].link].max;
} else{
int len = X - l[i] + 1;
//长度在1..len都不行
if(len < sam.T[sam.T[x].link].max){
ans += sam.T[x].max - sam.T[sam.T[x].link].max;
} else{
ans += max(0,sam.T[x].max - len);
break;
}
}
}
}
for(;top;top--) vis[st[top]] = false;
writeln(ans);
}
return 0;
}
文章目录
  1. 1. 「NOI2018」归程
  2. 2. 「NOI2018」你的名字