T20200827

T1 achen

就是考虑目标节点可能从那些地方转移过来,然后就得到了\(f[i]=f[i-1]+f[i-3]\)

然后基本上就结束了

Code

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
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
inline ll Read()
{
ll X(0);
char O(getchar());
while (O < '0' || O > '9') O = getchar();
for (; O >= '0' && O <= '9'; O = getchar()) X = (X << 1) + (X << 3) + (O ^ 48);
return X;
}

const ll Maxn = 1e6 + 10, Mod = 998244353;
ll Feb[Maxn] = {1};
ll T, N, A, B;

int main()
{
T = Read();
for (int i = 0; i < Maxn; ++i) Feb[i] %= Mod, Feb[i + 1] += Feb[i], Feb[i + 3] += Feb[i];
while (T--)
{
N = Read(), A = Read(), B = Read();
if (A > B) swap(A, B);
if (A > 1) A += 1;
if (B < N) B -= 1;
if (B < A) puts("0");
else printf ("%lld\n", Feb[B - A]);
}
return 0;
}

T2 Tree

考场思路:

对于\(Subtas1\):暴力换根

对于\(Subtas2\):树的直径

非常好,全写挂了,又因为是\(Subtask\), 就只有零分

Code

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
#include <bits/stdc++.h>

using namespace std;
const int Maxn = 1e6 + 100;
int Head[Maxn], Next[Maxn << 1], E[Maxn << 1], Cur;
int Col[Maxn], Fa[Maxn][20], Dep[Maxn], Max[Maxn];
int In[Maxn], Se[Maxn], Out[Maxn], Tim;
bool Vis1[Maxn], Vis2[Maxn];
vector <int> V[Maxn];

inline int Read()
{
int X(0);
char O = getchar();
while (O < '0' || O > '9') O = getchar();
for (; O >= '0' && O <= '9'; O = getchar()) X = (X << 1) + (X << 3) + (O ^ 48);
return X;
}

inline void AddEdge(int U, int V)
{
Next[++Cur] = Head[U];
Head[U] = Cur;
E[Cur] = V;
}

void DFS(int U, int F)
{
In[U] = ++Tim, Max[U] = Dep[U] = Dep[Fa[U][0] = F] + 1;
for (int i = Head[U]; i; i = Next[i])
if (E[i] != F) DFS(E[i], U);
for (int i = Head[U]; i; i = Next[i])
if (E[i] != F)
{
if (Max[E[i]] >= Max[U]) Se[U] = Max[U], Max[U] = Max[E[i]];
else if (Max[E[i]] >= Se[U]) Se[U] = Max[E[i]];
}
Out[U] = Tim;
}

int F_LCA(int U, int V)
{
if (Dep[U] < Dep[V]) swap(U, V);
for (int i = 0; i < 20; ++i)
if (((Dep[U] - Dep[V]) >> i) & 1) U = Fa[U][i];
if (U == V) return U;
for (int i = 19; i >= 0; --i)
if (Fa[U][i] != Fa[V][i]) U = Fa[U][i], V = Fa[V][i];
return Fa[U][0];
}

bool Cmp(int X, int Y){return In[X] < In[Y];}

int A[Maxn], L, R, Cnt, Ans;
int Ct[Maxn], Rit[Maxn];

void DFS_2(int U, int Val)
{
for (int i = Head[U]; i; i = Next[i])
if (!Vis1[E[i]]) Ans = max(Ans, Max[E[i]] - Dep[U] + 1);
if (Vis2[U]) Ans = max(Ans, Dep[U] + Val);
for (int i = Head[U]; i; i = Next[i])
if (E[i] != Fa[U][0])
{
if (Max[E[i]] == Max[U]) DFS_2(E[i], max(Val, Se[U] - 2 * Dep[U] + 1));
else DFS_2(E[i], max(Val, Max[U] - 2 * Dep[U] + 1));
}
}

int main()
{
int N = Read(), M = Read(), X, Y, LCA;
for (int i = 1; i <= N; ++i) V[Col[i] = Read()].push_back(i);
for (int i = 1; i < N; ++i)
{
X = Read(), Y = Read();
AddEdge (X, Y), AddEdge(Y, X);
}
DFS(1, 0);
for (int i = 1; i <= 19; ++i)
for (int j = 1; j <= N; ++j)
Fa[j][i] = Fa[Fa[j][i - 1]][i - 1];
for (int i = 1; i <= M; ++i)
{
X = V[i][0];
for (int j = 1; j < V[i].size(); ++j)
LCA = F_LCA(V[i][j], V[i][j - 1]), X = Dep[X] < Dep[LCA] ? X : LCA;
while (X && !Vis1[X]) Vis1[X] = 1, X = Fa[X][0];
}
for (int i = 1; i <= N; ++i) A[In[i]] = Col[i];
for (L = 1; L <= N; ++L)
{
while (Cnt != M && R <= N)
{
++R;
if (!Ct[A[R]]) ++Cnt;
++Ct[A[R]];
}
if (Cnt != M && R == N)
{
for (int i = L; i <= N; ++i) Rit[i] = N + 1;
break;
}
Rit[L] = R, --Ct[A[L]];
if (!Ct[A[L]]) --Cnt;
}
for (int i = 1; i <= N; ++i)
if (Out[i] >= Rit[In[i]]) Vis2[i] = 1;
DFS_2(1, 0);
printf ("%d\n", Ans);
}

T3 easy

没看出来这道题有多么\(easy\)mdzz

考场\(n^2\)暴力:枚举\(l,\;r\), 用\(map\)维护乱搞一通,检验连续的数的个数和区间长度的关系,就完了

Code

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
#include <bits/stdc++.h>
#define Val first
#define Pos second
#define LS (X << 1)
#define RS (X << 1 | 1)
#define Mid ((L + R) >> 1)
#define Node(X, Y) make_pair(X, Y)

using namespace std;

typedef long long ll;
const int Maxn = 1e5 + 10, Mod = 1e9 + 7;

int N, M, Last[Maxn], Now[Maxn];
int A[Maxn], B[Maxn];
ll Ans;
int Min[Maxn << 2], Cnt[Maxn << 2], Tag[Maxn << 2];

inline void PushUp(int X)
{
Min[X] = min(Min[LS], Min[RS]), Cnt[X] = 0;
if (Min[X] == Min[LS]) Cnt[X] += Cnt[LS];
if (Min[X] == Min[RS]) Cnt[X] += Cnt[RS];
}

inline void F(int X, int V)
{
Min[X] += V;
Tag[X] += V;
}

inline void PushDown(int X)
{
if (!Tag[X]) return ;
F(LS, Tag[X]), F(RS, Tag[X]);
Tag[X] = 0;
}

void Build(int L, int R, int X = 1)
{
if (L == R)
{
Min[X] = 0, Cnt[X] = 1;
return;
}
Build(L, Mid, LS);
Build(Mid + 1, R, RS);
}

inline void UpDate(int L, int R, int Tl, int Tr, int V, int X = 1)
{
if (L >= Tl && R <= Tr)
{
F(X, V) ;
return ;
}
PushDown(X);
if (Tl <= Mid) UpDate (L, Mid, Tl, Tr, V, LS);
if (Tr > Mid) UpDate (Mid + 1, R, Tl, Tr, V, RS);
PushUp(X);
}

int Query(int L, int R, int Tl, int Tr, int X = 1)
{
if (L >= Tl && R <= Tr)
{
if (Min[X] == -1) return Cnt[X];
else return 0;
}
int Ans(0); PushDown(X);
if (Tl <= Mid) Ans += Query (L, Mid, Tl, Tr, LS);
if (Tr > Mid) Ans += Query (Mid + 1, R, Tl, Tr, RS);
return Ans;
}

stack <pair <int, int> > Gtr, Les;

int main()
{
scanf ("%d", &N);
for (int i = 1; i <= N; ++i) scanf ("%d", A + i), B[i] = A[i];
sort (B + 1, B + N + 1);
M = unique (B + 1, B + N + 1) - B - 1;
for (int i = 1; i <= N; ++i)
{
int Temp = lower_bound(B + 1, B + M + 1, A[i]) - B;
Last[i] = Now[Temp], Now[Temp] = i;
}
Build(1, N);
Gtr.push(Node(0, 0)), Les.push(Node(Mod, 0));
for (int i = 1; i <= N; ++i)
{
while (Les.size() && Les.top().Val <= A[i])
{
pair <int, int> Top = Les.top(); Les.pop();
UpDate(1, N, Les.top().Pos + 1, Top.Pos, A[i] - Top.Val);
}
Les.push(Node(A[i], i));

while (Gtr.size() && Gtr.top().Val >= A[i])
{
pair <int, int> Top = Gtr.top(); Gtr.pop();
UpDate(1, N, Gtr.top().Pos + 1, Top.Pos, Top.Val - A[i]);
}
Gtr.push(Node(A[i], i));

UpDate(1, N, Last[i] + 1, i, -1);
Ans += Query(1, N, 1, i);
}
printf ("%lld\n", Ans);
}

因为人懒,今天就先放一个官方题解吧