杂题小记(2023.02.28)更好的阅读体验戳此进入SP2713 GSS4 - Can you answer these queries IV题面SolutionCodeLG-P4391 [BOI2009]Radio Transmission 无线传输题面SolutionCodeLG-P2375 [NOI2014] 动物园题面SolutionCodeLG-P3193 [HNOI2008]GT考试题面SolutionCodeLG-P4180 [BJWC2010] 严格次小生成树题面SolutionCodeLG-P3403 跳楼机题面SolutionCodeUPD
给定序列,区间开方,区间求和。
考虑对于
xxxxxxxxxx107123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23
24
25template < typename T = int >26inline T read(void);27
28int N, M;29ll A[110000];30
31class SegTree{32private:33 ll sum[110000 << 2];34 bool flag[110000 << 2];35 36 37 38public:39 void Clear(int p = 1, int gl = 1, int gr = N){40 sum[p] = flag[p] = 0;41 if(gl == gr)return;42 Clear(LS, gl, MID), Clear(RS, MID + 1, gr);43 }44 void Pushup(int p){45 sum[p] = sum[LS] + sum[RS];46 flag[p] = flag[LS] & flag[RS];47 }48 void Build(int p = 1, int gl = 1, int gr = N){49 if(gl == gr)return sum[p] = A[gl = gr], flag[p] = sum[p] == 0 || sum[p] == 1, void();50 Build(LS, gl, MID), Build(RS, MID + 1, gr);51 Pushup(p);52 }53 void Modify(int l, int r, int p = 1, int gl = 1, int gr = N){54 if(gl == gr)return sum[p] = (int)sqrt(sum[p]), flag[p] = sum[p] == 0 || sum[p] == 1, void();55 if(flag[p])return;56 if(l <= MID)Modify(l, r, LS, gl, MID);57 if(r >= MID + 1)Modify(l, r, RS, MID + 1, gr);58 Pushup(p);59 }60 ll Query(int l, int r, int p = 1, int gl = 1, int gr = N){61 if(l <= gl && gr <= r)return sum[p];62 if(l > gr || r < gl)return 0;63 return Query(l, r, LS, gl, MID) + Query(l, r, RS, MID + 1, gr);64 }65}st;66
67int main(){68 int cnt(0);69 while(true){70 N = read();71 // if(!~N)exit(0);72 printf("Case #%d:\n", ++cnt);73 for(int i = 1; i <= N; ++i)A[i] = read < ll >();74 st.Build();75 M = read();76 while(M--){77 int opt = read();78 if(opt == 0){79 int l = read(), r = read();80 st.Modify(min(l, r), max(l, r));81 }else{82 int l = read(), r = read();83 printf("%lld\n", st.Query(min(l, r), max(l, r)));84 }85 }printf("\n");86 st.Clear();87 }88 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);89 return 0;90}91
92template < typename T >93inline T read(void){94 T ret(0);95 int flag(1);96 char c = getchar();97 if(c == EOF)exit(0);98 while(c != '-' && !isdigit(c))c = getchar();99 if(c == '-')flag = -1, c = getchar();100 while(isdigit(c)){101 ret *= 10;102 ret += int(c - '0');103 c = getchar();104 }105 ret *= flag;106 return ret;107}给定字符串,其是由一个字符串多次重复得到的(是一个串无限重复后串的任意子串),求该字符串的最短长度。
只能说这题确实高妙!感觉推导过程和 border 的那一套理论差不多。
首先结论就是用 KMP 求出
按照类似 border 某些前置知识的证明思路证明即可,也就是考虑对于减去最长前后缀后剩下的一段,会对应着前缀末尾段,然后再对应到后缀对应段,一直对应下去,发现一定合法。
对于其一定为最优的证明,可以考虑若存在一个更小的循环节,多次循环之后最后会剩一个残块,不考虑这个残块及其影响后一定会形成一个更长前后缀,得证(这东西适合画图李姐一下,口糊肯定很抽象)。
xxxxxxxxxx60123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
2324
25template < typename T = int >26inline T read(void);27
28int N;29string S;30int nxt[1100000];31
32int main(){33 N = read();34 cin >> S;35 int lst(0);36 for(int i = 2; i <= N; ++i){37 while(lst && S(lst + 1) != S(i))lst = nxt[lst];38 if(S(lst + 1) == S(i))++lst;39 nxt[i] = lst;40 }printf("%d\n", N - nxt[N]);41
42 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);43 return 0;44}45
46template < typename T >47inline T read(void){48 T ret(0);49 int flag(1);50 char c = getchar();51 while(c != '-' && !isdigit(c))c = getchar();52 if(c == '-')flag = -1, c = getchar();53 while(isdigit(c)){54 ret *= 10;55 ret += int(c - '0');56 c = getchar();57 }58 ret *= flag;59 return ret;60}给定字符串
想麻烦了,找了半天性质,实际上很简单。
首先不考虑重叠,对于一般的求数量我们只需要在求
xxxxxxxxxx76123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
232425
26template < typename T = int >27inline T read(void);28
29string S;30int nxt[1100000];31int num[1100000];32
33int main(){34 int T = read();35 while(T--){36 ll ans(1);37 cin >> S;38 int N = S.length();39 int lst(0);40 nxt[0] = nxt[1] = num[0] = 0, num[1] = 1;41 for(int i = 2; i <= N; ++i){42 while(lst && S(lst + 1) != S(i))lst = nxt[lst];43 if(S(lst + 1) == S(i))++lst;44 nxt[i] = lst, num[i] = num[lst] + 1;45 }lst = 0;46 for(int i = 2; i <= N; ++i){47 while(lst && S(lst + 1) != S(i))lst = nxt[lst];48 if(S(lst + 1) == S(i))++lst;49 while(lst > (i >> 1))lst = nxt[lst];50 (ans *= (num[lst] + 1)) %= MOD;51 }52 // int same(1);53 // while(same + 1 <= N && S(same + 1) == S(same))++same;54 // ll ans(1);55 // for(int i = 1; i <= N; ++i)(ans *= nxt[i] ? (S(1) == S(i) ? min(nxt[i] + 1, same + 1) : 2) : 1) %= MOD;56 printf("%lld\n", ans);57 }58 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);59 return 0;60}61
62template < typename T >63inline T read(void){64 T ret(0);65 int flag(1);66 char c = getchar();67 while(c != '-' && !isdigit(c))c = getchar();68 if(c == '-')flag = -1, c = getchar();69 while(isdigit(c)){70 ret *= 10;71 ret += int(c - '0');72 c = getchar();73 }74 ret *= flag;75 return ret;76}求长度为
首先按照一般思路考虑一个朴素 DP,即令
显然可以等效写成:
发现其满足矩阵形式,且
对于
xxxxxxxxxx107123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
232425
26template < typename T = int >27inline T read(void);28
29int N, M, K;30string S;31int nxt[30];32int G[30][30];33
34class Matrix{35private:36public:37 int v[20][20];38 Matrix(void){memset(v, 0, sizeof v);}39 friend Matrix operator * (const Matrix &a, const Matrix &b){40 Matrix ret;41 for(int i = 0; i < M; ++i)42 for(int j = 0; j < M; ++j)43 for(int k = 0; k < M; ++k)44 (ret.v[i][j] += a.v[i][k] * b.v[k][j] % MOD) %= MOD;45 return ret;46 }47 void Print(void){48 printf("Matrix:\n");49 for(int i = 0; i < M; ++i)50 for(int j = 0; j < M; ++j)51 printf("%d%c", v[i][j], j == M - 1 ? '\n' : ' ');52 }53}base, ans;54
55Matrix qpow(Matrix a, ll b){56 Matrix ret, mul(a);57 for(int i = 0; i < M; ++i)ret.v[i][i] = 1;58 while(b){59 if(b & 1)ret = ret * mul;60 b >>= 1;61 mul = mul * mul;62 }return ret;63}64
65int main(){66 N = read(), M = read(), K = read();67 cin >> S;68 int lst(0);69 for(int i = 2; i <= M; ++i){70 while(lst && S(lst + 1) != S(i))lst = nxt[lst];71 if(S(lst + 1) == S(i))++lst;72 nxt[i] = lst;73 }74 for(int i = 0; i < M; ++i)75 for(int j = '0'; j <= '9'; ++j){76 int lst = i;77 while(lst && S(lst + 1) != j)lst = nxt[lst];78 if(S(lst + 1) == j)++lst;79 ++G[i][lst];80 }81 for(int i = 0; i < M; ++i)82 for(int j = 0; j < M; ++j)83 base.v[i][j] = G[i][j] % MOD;84 ans.v[0][0] = 1;85 ans = ans * qpow(base, N);86 int rans(0);87 for(int i = 0; i < M; ++i)(rans += ans.v[0][i]) %= MOD;88 printf("%d\n", rans);89 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);90 return 0;91}92
93template < typename T >94inline T read(void){95 T ret(0);96 int flag(1);97 char c = getchar();98 while(c != '-' && !isdigit(c))c = getchar();99 if(c == '-')flag = -1, c = getchar();100 while(isdigit(c)){101 ret *= 10;102 ret += int(c - '0');103 c = getchar();104 }105 ret *= flag;106 return ret;107}求连通图的严格次小生成树。
存在如下方法,正确性可感性理解,理性证明未知。
考虑任意建出一棵 MST,然后枚举所有没有在 MST 中的边,分别找出每条边的
对于维护可以考虑用树剖 + 线段树,边权下放到点权,然后合并时可以强行讨论,也可无脑开 basic_string 排序后 unique 实现,此写法常数较大但可以通过。
xxxxxxxxxx182123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23template < typename T = int >24inline T read(void);25
26int N, M;27struct Edge{28 Edge* nxt;29 int to;30 int val;31 OPNEW;32}ed[210000];33ROPNEW;34Edge* head[110000];35
36class UnionFind{37private:38 int fa[110000];39public:40 UnionFind(void){for(int i = 0; i <= 101000; ++i)fa[i] = i;}41 int Find(int x){return x == fa[x] ? x : fa[x] = Find(fa[x]);}42 void Union(int s, int t){int fs = Find(s), ft = Find(t); fa[fs] = ft;}43}uf;44
45struct Edg{int s, t, v;};46basic_string < Edg > edgs;47basic_string < Edg > trash;48
49int dep[110000], fa[110000], hson[110000], siz[110000], dfn[110000], idx[110000], top[110000];50
51void dfs_pre(int p = 1, int fa = 0){52 ::fa[p] = fa, dep[p] = dep[fa] + 1, siz[p] = 1;53 for(auto i = head[p]; i; i = i->nxt){54 if(SON == fa)continue;55 dfs_pre(SON, p);56 siz[p] += siz[SON];57 if(siz[SON] > siz[hson[p]])hson[p] = SON;58 }59}60void dfs_make(int p = 1, int top = 1){61 static int cdfn(0);62 dfn[p] = ++cdfn, idx[cdfn] = p, ::top[p] = top;63 if(hson[p])dfs_make(hson[p], top);64 for(auto i = head[p]; i; i = i->nxt)65 if(SON != fa[p] && SON != hson[p])dfs_make(SON, SON);66}67
68ll ans(LONG_LONG_MAX);69int val[110000];70
71void PushdownVal(int p = 1, int fa = 0){72 for(auto i = head[p]; i; i = i->nxt)73 if(SON != fa)74 val[SON] = i->val, PushdownVal(SON, p);75}76
77class SegTree{78private:79 int mx[110000 << 2], mx2[110000 << 2];80 81 82 83public:84 SegTree(void){memset(mx, -1, sizeof mx), memset(mx2, -1, sizeof mx2);}85 void Pushup(int p){86 basic_string < int > vals;87 if(~mx[LS])vals += mx[LS];88 if(~mx[RS])vals += mx[RS];89 if(~mx2[LS])vals += mx2[LS];90 if(~mx2[RS])vals += mx2[RS];91 sort(vals.begin(), vals.end(), greater < int >());92 vals.erase(unique(vals.begin(), vals.end()), vals.end());93 mx[p] = (int)vals.size() >= 1 ? *vals.begin() : -1;94 mx2[p] = (int)vals.size() >= 2 ? *next(vals.begin()) : -1;95 }96 void Build(int p = 1, int gl = 1, int gr = N){97 if(gl == gr)return mx[p] = val[idx[gl = gr]], void();98 Build(LS, gl, MID), Build(RS, MID + 1, gr);99 Pushup(p);100 }101 pair < int, int > Query(int l, int r, int p = 1, int gl = 1, int gr = N){102 if(l <= gl && gr <= r)return {mx[p], mx2[p]};103 if(l > gr || r < gl)return {-1, -1};104 basic_string < int > vals;105 auto ret = Query(l, r, LS, gl, MID);106 if(~ret.first)vals += ret.first;107 if(~ret.second)vals += ret.second;108 ret = Query(l, r, RS, MID + 1, gr);109 if(~ret.first)vals += ret.first;110 if(~ret.second)vals += ret.second;111 sort(vals.begin(), vals.end(), greater < int >());112 vals.erase(unique(vals.begin(), vals.end()), vals.end());113 return {(int)vals.size() >= 1 ? *vals.begin() : -1, (int)vals.size() >= 2 ? *next(vals.begin()) : -1};114 }115}st;116
117ll origin(0);118
119int QueryMx2(int s, int t, int ban){120 basic_string < int > vals;121 while(top[s] != top[t]){122 if(dep[top[s]] < dep[top[t]])swap(s, t);123 auto ret = st.Query(dfn[top[s]], dfn[s]);124 if(~ret.first)vals += ret.first;125 if(~ret.second)vals += ret.second;126 // printf("Querying %d->%d, [%d, %d], ret %d %d\n", top[s], s, dfn[top[s]], dfn[s], ret.first, ret.second);127 s = fa[top[s]];128 }if(dep[s] < dep[t])swap(s, t);129 auto ret = st.Query(dfn[hson[t]], dfn[s]);130 // printf("Querying %d->%d, [%d, %d], ret %d %d\n", hson[t], s, dfn[hson[t]], dfn[s], ret.first, ret.second);131 if(~ret.first)vals += ret.first;132 if(~ret.second)vals += ret.second;133 sort(vals.begin(), vals.end(), greater < int >());134 vals.erase(unique(vals.begin(), vals.end()), vals.end());135 int mx = (int)vals.size() >= 1 ? *vals.begin() : -1, mx2 = (int)vals.size() >= 2 ? *next(vals.begin()) : -1;136 return mx != ban ? mx : mx2;137}138
139int main(){140 N = read(), M = read();141 for(int i = 1; i <= M; ++i){142 int s = read(), t = read(), v = read();143 if(s == t)continue;144 edgs += Edg{s, t, v};145 }sort(edgs.begin(), edgs.end(), [](const Edg &a, const Edg &b)->bool{return a.v < b.v;});146 for(auto edg : edgs){147 auto [s, t, v] = edg;148 if(uf.Find(s) != uf.Find(t))149 head[s] = new Edge{head[s], t, v},150 head[t] = new Edge{head[t], s, v},151 origin += v,152 uf.Union(s, t);153 else trash += edg;154 }dfs_pre(), dfs_make(), PushdownVal();155 st.Build();156 // printf("origin is %lld\n", origin);157 for(auto edg : trash){158 auto [s, t, v] = edg;159 int ret = QueryMx2(s, t, v);160 if(!~ret)continue;161 // printf("[%d - %d], v = %d, ret = %d\n", s, t, v, ret);162 ans = min(ans, origin - ret + v);163 }printf("%lld\n", ans);164 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);165 return 0;166}167
168template < typename T >169inline T read(void){170 T ret(0);171 int flag(1);172 char c = getchar();173 while(c != '-' && !isdigit(c))c = getchar();174 if(c == '-')flag = -1, c = getchar();175 while(isdigit(c)){176 ret *= 10;177 ret += int(c - '0');178 c = getchar();179 }180 ret *= flag;181 return ret;182}给定
经典同余最短路问题,令
xxxxxxxxxx86123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23template < typename T = int >24inline T read(void);25
26ll H;27int x, y, z;28
29struct Edge{30 Edge* nxt;31 int to;32 int val;33 OPNEW;34}ed[210000];35ROPNEW;36Edge* head[110000];37
38bitset < 110000 > vis;39ll dis[110000];40ll ans(0);41
42void Dijkstra(void){43 memset(dis, 0x3f, sizeof dis);44 static priority_queue < pair < ll, int >, vector < pair < ll, int > >, greater < pair < ll, int > > > cur;45 dis[1] = 1, cur.push({0, 1});46 while(!cur.empty()){47 int p = cur.top().second; cur.pop();48 if(vis[p])continue;49 vis[p] = true;50 for(auto i = head[p]; i; i = i->nxt)51 if(dis[p] + i->val < dis[SON])52 dis[SON] = dis[p] + i->val, cur.push({dis[SON], SON});53 }54}55
56int main(){57 H = read < ll >();58 x = read(), y = read(), z = read();59 if(x == 1 || y == 1 || z == 1)printf("%lld\n", H), exit(0);60 for(int i = 0; i < x; ++i)61 head[i] = new Edge{head[i], (i + y) % x, y},62 head[i] = new Edge{head[i], (i + z) % x, z};63 Dijkstra();64 for(int i = 0; i < x; ++i)65 if(H >= dis[i])66 ans += (H - dis[i]) / x + 1;67 printf("%lld\n", ans);68 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);69 return 0;70}71
72template < typename T >73inline T read(void){74 T ret(0);75 int flag(1);76 char c = getchar();77 while(c != '-' && !isdigit(c))c = getchar();78 if(c == '-')flag = -1, c = getchar();79 while(isdigit(c)){80 ret *= 10;81 ret += int(c - '0');82 c = getchar();83 }84 ret *= flag;85 return ret;86}update-2023_02_28 初稿