首页 > 其他分享 >CodeForces 1246F Cursor Distance

CodeForces 1246F Cursor Distance

时间:2023-10-30 17:44:50浏览次数:43  
标签:Distance typedef int 字符集 long Cursor maxn 1246F define

洛谷传送门

CF 传送门

发现一个性质:能跳不超过 \(j\) 步到达 \(i\) 的所有点形成一段区间。设这这段区间为 \([L_{i, j}, R_{i, j}]\)。

那么答案即为:

\[\sum\limits_{i = 1}^n \sum\limits_{j = 0} n - R_{i, j} + L_{i, j} - 1 \]

并且:

\[[L_{i, j}, R_{i, j}] = \bigcup\limits_{k \in [L_{i, j - 1}, R_{i, j - 1}]} [L_{k, 1}, R_{k, 1}] \]

\(L_{i, 1}\) 和 \(R_{i, 1}\) 分别是 \(i\) 左侧和右侧第一个字符和 \(s_i\) 相等的位置,\(L_{i, 0} = R_{i, 0} = i\)。

现在我们想优化暴力跳的过程。一个自然的想法是倍增。但是跳的过程涉及到 \(L, R\) 两个量的变化,它们不互相独立,不太好维护。

但是又发现,最右边(或最左边)的一些字符对 \(L\)(或 \(R\))的转移没用。比如 \(\texttt{abcab}\),最右边的 \(\texttt{ab}\) 由于前面出现过所以不会对 \(L_{i, j}\) 有贡献。

也就是说 \(L_{i, j} = \min\limits_{k \in [L_{i, j - 1}, T]}\),其中 \(T\) 是最小的满足 \([L_{i, j - 1}, T]\) 和 \([L_{i, j - 1}, R_{i, j - 1}]\) 的字符集相等的位置。所以如果固定字符集大小和 \(L_{i, j - 1}\),那么 \(L_{i, j}\) 能直接不依赖 \(R_{i, j - 1}\) 计算出来。对于 \(R\) 也类似。

字符集只会变化 \(O(|\Sigma|)\) 次。于是可以枚举字符集大小 \(k\),然后同时维护 \(4\) 个倍增数组:

  • \(fl_{i, c}\) 表示对于一个 \(L_{t, j - 1} = i\),它在一开始字符集大小为 \(k\) 的情况下,跳 \(2^c\) 步后的位置。
  • \(gl_{i, c}\) 表示 \(L\) 跳 \(2^c\) 步经过的所有点的和。
  • \(fr_{i, c}\) 表示对于一个 \(R_{t, j - 1} = i\),它在一开始字符集大小为 \(k\) 的情况下,跳 \(2^c\) 步后的位置。
  • \(gr_{i, c}\) 表示 \(R\) 跳 \(2^c\) 步经过的所有点的和。

倍增跳到最大的 \(L\) 和 \(R\) 满足 \([L, R]\) 中的字符集大小为 \(k\) 即可。

时间复杂度 \(O(n |\Sigma| \log n)\)。

code
// Problem: F. Cursor Distance
// Contest: Codeforces - Codeforces Round 596 (Div. 1, based on Technocup 2020 Elimination Round 2)
// URL: https://codeforces.com/problemset/problem/1246/F
// Memory Limit: 512 MB
// Time Limit: 2000 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<ll, ll> pii;

const int maxn = 100100;

int n, pre[maxn][26], nxt[maxn][26];
int L[maxn], R[maxn], pr[maxn], nx[maxn], fl[20][maxn], fr[20][maxn];
ll gl[20][maxn], gr[20][maxn];
char s[maxn];

inline bool check(int l, int r, int k) {
	return k == 26 || nxt[l][k] > r;
}

void solve() {
	scanf("%s", s + 1);
	n = strlen(s + 1);
	for (int i = 1; i <= n; ++i) {
		L[i] = R[i] = i;
	}
	for (int i = 0; i < 26; ++i) {
		pre[0][i] = 1;
		nxt[n + 1][i] = n;
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 0; j < 26; ++j) {
			pre[i][j] = pre[i - 1][j];
		}
		pre[i][s[i] - 'a'] = i;
	}
	for (int i = n; i; --i) {
		for (int j = 0; j < 26; ++j) {
			nxt[i][j] = nxt[i + 1][j];
		}
		nxt[i][s[i] - 'a'] = i;
	}
	for (int i = 1; i <= n; ++i) {
		fl[0][i] = pr[i] = pre[i - 1][s[i] - 'a'];
		fr[0][i] = nx[i] = nxt[i + 1][s[i] - 'a'];
		L[i] = R[i] = i;
	}
	for (int i = 1; i <= n; ++i) {
		sort(pre[i], pre[i] + 26, greater<int>());
		sort(nxt[i], nxt[i] + 26);
	}
	ll ans = 0;
	for (int k = 1; k <= 26; ++k) {
		for (int i = 1; i <= n; ++i) {
			fl[0][i] = gl[0][i] = min(fl[0][i], pr[nxt[i][k - 1]]);
			fr[0][i] = gr[0][i] = max(fr[0][i], nx[pre[i][k - 1]]);
		}
		for (int j = 1; j <= 18; ++j) {
			for (int i = 1; i <= n; ++i) {
				fl[j][i] = fl[j - 1][fl[j - 1][i]];
				fr[j][i] = fr[j - 1][fr[j - 1][i]];
				gl[j][i] = gl[j - 1][i] + gl[j - 1][fl[j - 1][i]];
				gr[j][i] = gr[j - 1][i] + gr[j - 1][fr[j - 1][i]];
			}
		}
		for (int i = 1; i <= n; ++i) {
			if (check(L[i], R[i], k)) {
				ans += n - 1 - R[i] + L[i];
				for (int j = 18; ~j; --j) {
					int l = fl[j][L[i]], r = fr[j][R[i]];
					if (check(l, r, k)) {
						ans += (1LL << j) * (n - 1) - gr[j][R[i]] + gl[j][L[i]];
						L[i] = l;
						R[i] = r;
					}
				}
				L[i] = fl[0][L[i]];
				R[i] = fr[0][R[i]];
			}
		}
	}
	printf("%lld\n", ans);
}

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

标签:Distance,typedef,int,字符集,long,Cursor,maxn,1246F,define
From: https://www.cnblogs.com/zltzlt-blog/p/17798425.html

相关文章

  • AT_abc301_h [ABC301Ex] Difference of Distance
    AT_abc301_h[ABC301Ex]DifferenceofDistance更好的阅读体验一道基础图论,很好口胡,但是实现不太简单。考虑离线,把询问挂在边上,按边权从小到大处理。处理到一个边权时,把边权小于它的边的两端用并查集合并,对于等于这个边权的边在并查集上建图,跑一边tarjan,因为问的是边,所以把......
  • * Codeforces Round 665 (Div. 2) A. Distance and Axis
    有一个点\(A\)在\(OX\)正坐标轴上的\(x\)坐标为\(n\)。需要找到一个点\(B\),使得\(||OB|-|AB||=k\)。现在给出非负整数\(n\)\(k\),你可以执行任意次以下操作:每步操作可以使\(A\)的坐标加一或减一。询问最少需要进过多少次操作使\(B\)可以存在。先假设出......
  • Codeforces Round 903 (Div. 3) F. Minimum Maximum Distance(图论)
    CodeforcesRound903(Div.3)F.MinimumMaximumDistance思路对标记点更新fg,从0开始进行bfs,更新d1为所有点到0的距离获得到0最远的标记点L,从L开始bfs,更新d2为所有点到L的距离获得距离L最远的标记点R,从R开始bfs,更新d3为所有点到R的距离遍历所有点,这个点与标记点的最大距......
  • CF1881F Minimum Maximum Distance
    给定一棵树,树上的一些点被打上了标记,定义一个节点的贡献为其到所有标记节点距离的最大值,求最小贡献。\(n\le2\times10^5\)。这道题的原题是CF337D(甚至要更困难一些)。很套路的换根DP啊。我们考虑设\(f_i\)为\(i\)子树内的标记节点到\(i\)的最大距离,\(g_i\)为子......
  • System.NotSupportedException:“无法显式设置 SplitterPanel 的高度。改在 SplitCont
    System.NotSupportedException:“无法显式设置SplitterPanel的高度。改在SplitContainer上设置SplitterDistance。”这个错误信息是在使用SplitContainer控件时出现的。它表明您尝试显式设置SplitterPanel的高度,但这是不支持的操作,应该在SplitContainer上设置Splitte......
  • Oracle process/session/cursor/tx/tm的简单学习
    Oracleprocess/session/cursor/tx/tm的简单学习Oracle的部署模式Oracle安装时有专用模式和共享模式的区别共享模式(Sharedmode):在共享模式下,会话可以同时读取数据库的数据,多个会话可以并发地进行读取操作。这意味着多个会话可以共享相同的数据快照,并且彼此之间不会阻塞。......
  • 基于pHash+hammingdistance的图片相似度比较
    参考文献图片相似度计算方法总结-知乎(zhihu.com)PythonOpenCV视觉特征提取和匹配-知乎(zhihu.com)图像相似度中的Hash算法-Yumeka-博客园(cnblogs.com)汉明距离及其高效计算方式(zhihu.com)开源仓库https://github.com/python-pillow/Pillowhttps://github.com/cybe......
  • 题解 [ARC165C] Social Distance on Graph
    赛时:看不懂题,啊这!赛后:就这?题目描述有一个简单相连的无向图,其顶点数为\(n\),编号为\(1\)至\(n\)。图中有\(m\)条加权边,第\(i\)条边连接顶点\(a_i\)和\(b_i\),权重为\(w_i\)。此外,连接两个顶点的简单路径的权重是简单路径中包含的边的权重之和。我们给每个顶点涂上红......
  • 并行insert出现library cache lock与cursor: pin S wait on X等待问题记录
    一、故障现象与紧急处理开发反馈凌晨5点左右应用出现大量报错 ORA-04021:timeoutoccurredwhilewaitingtolockobject,并且集中出现在insertim_message这个表的操作上,其他表不受影响。查看当时等待情况,发现确实有异常的内存等待,而且还可以看到sid=15和1347的会话在相互等待,......
  • hdu 4712 Hamming Distance-----随机
    计算出二进制数中有多少个1:数据范围太大,想到可以随机如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。------百度rand#include<cstdio>#include<cstring>#include<algorithm>#include<time.h>usingnamespacestd;constintN=1e5+10......