首页 > 其他分享 >洛谷 P7409 SvT

洛谷 P7409 SvT

时间:2024-01-10 10:12:55浏览次数:36  
标签:typedef 洛谷 P7409 int text lsh maxn tot SvT

洛谷传送门

考虑对反串建 SAM,设 \([i, n]\) 的后缀对应 SAM 的点是 \(a_i\)。

那么 \(\text{lcp}(s[i : n], s[j : n]) = \text{len}(\text{lca}(a_i, a_j))\)。

于是问题变成了,给定一些点,统计两两 \(\text{lca}\) 点权之和。

考虑建虚树,枚举每个点 \(u\) 作为 \(\text{lca}\) 的次数。设当前已经考虑过的儿子的 \(sz\) 之和为 \(s\),那么 \(v\) 作为子树会有 \(s \times sz_v\) 次数的贡献。再乘上 \(len_u\) 累加进答案即可。

若使用 dfs 序 LCA,时间复杂度 \(O((n + \sum t) \log n)\)。

code
// Problem: P7409 SvT
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7409
// Memory Limit: 512 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;

const int maxn = 1000100;
const int logn = 22;

int n, m, lsh[maxn << 1], b[maxn], a[maxn * 3];
char s[maxn];
vector<int> G[maxn], T[maxn];

struct SAM {
	int lst, tot, fa[maxn], ch[maxn][26], len[maxn];
	
	inline void init() {
		for (int i = 1; i <= tot; ++i) {
			fa[i] = len[i] = 0;
			mems(ch[i], 0);
		}
		lst = tot = 1;
	}
	
	inline void insert(int c) {
		int u = ++tot, p = lst;
		len[u] = len[p] + 1;
		lst = u;
		for (; p && !ch[p][c]; p = fa[p]) {
			ch[p][c] = u;
		}
		if (!p) {
			fa[u] = 1;
			return;
		}
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {
			fa[u] = q;
			return;
		}
		int nq = ++tot;
		fa[nq] = fa[q];
		len[nq] = len[p] + 1;
		memcpy(ch[nq], ch[q], sizeof(ch[nq]));
		fa[u] = fa[q] = nq;
		for (; p && ch[p][c] == q; p = fa[p]) {
			ch[p][c] = nq;
		}
	}
} sam;

int st[logn][maxn], dfn[maxn], tim;

inline int get(int i, int j) {
	return dfn[i] < dfn[j] ? i : j;
}

inline int qlca(int x, int y) {
	if (x == y) {
		return x;
	}
	x = dfn[x];
	y = dfn[y];
	if (x > y) {
		swap(x, y);
	}
	++x;
	int k = __lg(y - x + 1);
	return get(st[k][x], st[k][y - (1 << k) + 1]);
}

void dfs(int u) {
	dfn[u] = ++tim;
	for (int v : G[u]) {
		dfs(v);
		st[0][dfn[v]] = u;
	}
}

ll f[maxn], ans;

void dfs2(int u) {
	for (int v : T[u]) {
		dfs2(v);
		ans += f[u] * f[v] * sam.len[u];
		f[u] += f[v];
	}
}

void solve() {
	scanf("%d%d%s", &n, &m, s + 1);
	sam.init();
	for (int i = n; i; --i) {
		sam.insert(s[i] - 'a');
		b[i] = sam.lst;
	}
	for (int i = 2; i <= sam.tot; ++i) {
		G[sam.fa[i]].pb(i);
	}
	dfs(1);
	for (int j = 1; (1 << j) <= tim; ++j) {
		for (int i = 1; i + (1 << j) - 1 <= tim; ++i) {
			st[j][i] = get(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]);
		}
	}
	while (m--) {
		int len, tot = 0;
		scanf("%d", &len);
		for (int i = 1; i <= len; ++i) {
			scanf("%d", &a[i]);
			a[i] = b[a[i]];
		}
		sort(a + 1, a + len + 1);
		len = unique(a + 1, a + len + 1) - a - 1;
		sort(a + 1, a + len + 1, [&](const int &x, const int &y) {
			return dfn[x] < dfn[y];
		});
		for (int i = 1; i <= len; ++i) {
			lsh[++tot] = a[i];
			if (i > 1) {
				lsh[++tot] = qlca(a[i - 1], a[i]);
			}
		}
		sort(lsh + 1, lsh + tot + 1);
		tot = unique(lsh + 1, lsh + tot + 1) - lsh - 1;
		sort(lsh + 1, lsh + tot + 1, [&](const int &x, const int &y) {
			return dfn[x] < dfn[y];
		});
		for (int i = 2; i <= tot; ++i) {
			T[qlca(lsh[i - 1], lsh[i])].pb(lsh[i]);
		}
		for (int i = 1; i <= len; ++i) {
			f[a[i]] = 1;
		}
		ans = 0;
		dfs2(lsh[1]);
		printf("%lld\n", ans % 23333333333333333LL);
		for (int i = 1; i <= tot; ++i) {
			vector<int>().swap(T[lsh[i]]);
			f[lsh[i]] = 0;
		}
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:typedef,洛谷,P7409,int,text,lsh,maxn,tot,SvT
From: https://www.cnblogs.com/zltzlt-blog/p/17955916

相关文章

  • 洛谷火柴人
    importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.io.StreamTokenizer;publicclassMain{staticintn;staticintnumber=0;staticint[]arr=newint[20000];staticboolean[]st=newboolean[20000];sta......
  • 【LGR-170-Div.3】洛谷基础赛 #6 & Cfz Round 3 & Caféforces #2
    这套题感觉质量很高A.Battle\[x\equivr(\bmodP)\]\[P\midx-r\]因此只有第一次操作是有效的voidsolve(){ intn,m,p; cin>>n>>m>>p; m-=m%p; if(!m)puts("Alice"); else{ n-=n%p; if(!n)puts("Bob"); else......
  • 洛谷 P5311 [Ynoi2011] 成都七中
    洛谷传送门转化一下题意,变成求\(x\)在只经过编号\(\in[l,r]\)的点,能走到多少种颜色。考虑建出点分树。一个结论是原树上的一个连通块,一定存在一个点,使得它在点分树上的子树完全包含这个连通块的所有点。证明考虑点分治的过程,一个连通块如果没被其中一个点剖开就一定在同一......
  • 洛谷 P9058 [Ynoi2004] rpmtdq
    洛谷传送门类比P9062[Ynoi2002]AdaptiveHsearch&Lsearch处理区间最近点对的思路,尝试只保留可能有贡献的点对。处理树上路径容易想到点分治。设点\(u\)到分治中心的距离为\(a_u\)。我们有\(\text{dis}(u,v)\lea_u+a_v\)。考虑一个点对\((u,v)\)什么时候一定没......
  • 洛谷B3611 【模板】传递闭包 floyd/bitset
    目录floydbitset优化题目链接:https://www.luogu.com.cn/problem/B3611参考题解:https://www.luogu.com.cn/blog/53022/solution-b3611floyd#include<bits/stdc++.h>usingnamespacestd;constintmaxn=101;intn,f[maxn][maxn];intmain(){scanf("%d"......
  • 洛谷B3647 【模板】Floyd 题解 floyd算法 求 多源多汇最短路
    题目链接:https://www.luogu.com.cn/problem/B3647floyd算法:https://oi-wiki.org/graph/shortest-path/#floyd-算法示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=101;intn,m,f[maxn][maxn];intmain(){scanf("%d%d",&n......
  • 【题解】洛谷P1496 火烧赤壁 (离散化)
    P1496火烧赤壁-洛谷|计算机科学教育新生态(luogu.com.cn)我们首先先看数据,n<=20000,数据不多,但是范围大(-10^9<=Ai,Bi<=10^9),这时,就可以用离散化了。但是在这里我们会遇到区间重合的问题(也可以使用区间合并),如下图本题的题意是让我们求出燃烧位置的长度之和。区间重合时只......
  • 【题解】洛谷P1068 [NOIP2009 普及组] 分数线划定 (map)
    ##题目描述世博会志愿者的选拔工作正在A市如火如荼的进行。为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的$150\%$划定,即如果计划录取$m$名志愿者,则面试分数线为排名第$m\times150\%$(向......
  • 洛谷 P1229
    题目链接有4种结构。对于只有一个儿子(度为1)的结点,其子节点在左/右不影响先序/后序的遍历顺序,总树数*2。即每多一个度为1的结点,二叉树数量翻倍。即当先根序列为\(.....XY.....,\)后根序列为\(.........YX...\)时翻倍。求出这种结构的个数即可。#include<bits/stdc++.h>usi......
  • 【洛谷 P1781】宇宙总统 题解(高精度+结构体排序)
    宇宙总统题目描述地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。输入格式第一行为一个整数,代表竞选总统的人数。接下来有行,分别为第一个候选人到第个候选人的票数。输出格式共两行,第一行是......