首页 > 其他分享 >CF213E Two Permutation 题解

CF213E Two Permutation 题解

时间:2023-12-13 19:57:42浏览次数:23  
标签:return CF213E int 题解 Two tag base c1 mod

CF213E Two Permutations 题解

题意:

给出两个排列$a,b $,长度分别为 \(n,m\),你需要计算有多少个 $ x $,使得 \(a_1 + x,a_2 + x,...a_n + x\) 是 \(b\) 的子序列。
\(n \leq m \leq 2 \times 10^5\)

分析:

一个很自然的思路是直接枚举 \(x\),然后只保留 \(b\) 中值域在 \([x+1,x+n]\) 的数,然后利用哈希判断 \(a\) 与 \(b\) 是否相同。

显然是可行的,看看如何维护 \(a\) 与 \(b\) 的哈希值。

维护 \(a\) 的哈希值是简单的,记 \(S = \sum_{i=1}^{n}a_i \times base^{n-i+1}\),显然

\[\sum_{i=1}^{n}(a_i+x) \times base^{n-i+1}=S+x\sum_{i=1}^{n}base^{n-i+1} \]

\(b\) 的哈希也不难,考虑保留值域从 \([l,r]\) 到 \([l+1,r+1]\) 的过程,明显删掉了 \(l\),加上了 \(r\)。

我们可以利用线段树动态维护每个点的 \(b_i \times base^{n-i+1}\),删掉一个数后前面的数都要除以 \(base\),加入一个数后前面的数都要乘上 \(base\)。

在线段树里面维护两个值 \(c_1,c_2\) 分别记录这个区间的 \(\sum b_i \times base^{n-i+1}\) 和里面有值的数的数量

这个线段树需要支持区间乘、单点赋值、区间查询。

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

代码:

#include<bits/stdc++.h>
#define int long long
#define base 1000000007
#define mod 998244353
#define N 200005
using namespace std;
int read() {
	char ch = getchar(); int x = 0, f = 1;
	while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}
void write(int x) {
	if(x < 0) putchar('-'), x = -x;
	if(x > 9) write(x / 10);
	putchar('0' + x % 10);
}
int Pow(int a, int n) {
	if(n == 0) return 1;
	if(n == 1) return a % mod;
	int x = Pow(a, n / 2);
	if(n % 2 == 0) return x * x % mod;
	else return x * x % mod * a % mod;
}
int inv(int x) {
	return Pow(x, mod - 2);
}
int n, m, hx, ans;
int a[N], b[N], h[N], f[N], S;
int c1[N * 4], c2[N * 4], tag[N * 4]; //c1记录hash值,c2记录有值的个数 
void pushup(int u) {
	c1[u] = (c1[u * 2] + c1[u * 2 + 1]) % mod;
	c2[u] = c2[u * 2] + c2[u * 2 + 1];
}
void maketag(int u, int x) {
	if(tag[u] != -1) tag[u] = tag[u] * x % mod; 
	else tag[u] = x % mod;
	if(c1[u] != -1) c1[u] = c1[u] * x % mod;
	else c1[u] = x % mod;
}
void pushdown(int u) {
	if(tag[u] == -1) return;
	maketag(u * 2, tag[u]);
	maketag(u * 2 + 1, tag[u]);
	tag[u] = -1;
}
void update1(int u, int L, int R, int x, int y) { //c1[x]=y 
	if(L == R) {
		if(c1[u] != 0 && y == 0) c2[u] = 0;
		else if(c1[u] == 0 && y != 0) c2[u] = 1;
		c1[u] = y;
		return;
	}
	int mid = (L + R) / 2;
	pushdown(u);
	if(x <= mid) update1(u * 2, L, mid, x, y);
	else update1(u * 2 + 1, mid + 1, R, x, y);
	pushup(u);
}
void update2(int u, int L, int R, int l, int r, int x) { //c1[l...r]乘上x 
	if(r < L || R < l) return;
	if(l <= L && R <= r) {
		maketag(u, x);
		return; 
	}
	pushdown(u);
	int mid = (L + R) / 2;
	update2(u * 2, L, mid, l, r, x);
	update2(u * 2 + 1, mid + 1, R, l, r, x);
	pushup(u);
}
int query(int u, int L, int R, int l, int r) { //查询[l,r]的c2 
	if(r < L || R < l) return 0;
	if(l <= L && R <= r) return c2[u];
	pushdown(u);
	int mid = (L + R) / 2;
	return query(u * 2, L, mid, l, r) + query(u * 2 + 1, mid + 1, R, l, r);
}
void Insert(int x, int y) { //在x处插入y 
    int z = query(1, 1, m, x + 1, m);
	update1(1, 1, m, x, y * h[z] % mod);
	update2(1, 1, m, 1, x - 1, base);
}
void Delete(int x) {
	update1(1, 1, m, x, 0);
	update2(1, 1, m, 1, x - 1, inv(base) % mod);
}
signed main() {
	memset(tag, -1, sizeof(tag));
    n = read(), m = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    for(int i = 1; i <= m; i++) b[i] = read(), f[b[i]] = i;
    h[0] = 1; 
	for(int i = 1; i <= 200000; i++) h[i] = h[i - 1] * base % mod;
	for(int i = 1; i <= n; i++) {
		S += h[n - i]; S %= mod;
		hx += a[i] * h[n - i] % mod; hx %= mod;
	}
	for(int i = 1; i <= n; i++) Insert(f[i], b[f[i]]);
	for(int x = 0; x <= m - n; x++) { //保留b值域为 [1+x, x+n] 的数 
		if(x) {
			hx += S % mod; hx %= mod;
			Delete(f[x]);
			Insert(f[x + n], b[f[x + n]]);
		}
		if(c1[1] == hx) ans++;
	}
	write(ans);
	return 0;
}

标签:return,CF213E,int,题解,Two,tag,base,c1,mod
From: https://www.cnblogs.com/xcs123/p/17899793.html

相关文章

  • 记一次 Zabbix agent is not available 问题解决
    好久没折腾zabbix,最近遇到一个奇葩的问题,忽然有一台服务器报警“Zabbixagentisnotavailable(ornodatafor30m)”,但是查看监控数据都有,而且在不断的更新开始分析问题、解决问题:1、先检查了一遍配置,都没问题2、检查了一遍server端和agent端的日志,也没有相应的错......
  • CF1500F Cupboards Jumps 题解
    题目链接点击打开链接题目解法感觉是一个融合了许多技巧的题,很巧妙题目要求\(\max(h_i,h_{i+1},h_{i+2})-\min(h_i,h_{i+1},h_{i+2})=w_i\),这可以转化成另一个只和两项有关的形式为:\(\max(|h_i-h_{i+1}|,|h_i-h_{i+2}|,|h_{i+1}-h_{i+2}|)=w_i\)令\(d_i=h_{i+1}-h_i\),所以......
  • springboot-micrometer潜在oom问题解决办法
    在服务中起一个监听Prometheus拉取的线程,在拉取完成之后清理调meterMap中内容比较多的tag,我这边是清理调gateway.requests.代码如下:@ComponentpublicclassPrometheusMeterRegistryFactory{@ResourceprivatePrometheusMeterRegistryprometheusMeterRegistry;......
  • CTFpwnAD世界pwnstack题解及栈溢出两种解法
    问题的出现这题我刚看到时差点没笑出来,但是尝试了一次之后我就笑不出来了。这题给了back_door后门函数,但是如果直接覆盖返回到后门函数起始位置会出现栈溢出问题。到这一步都没有出现问题,而继续ni的话就会卡住。基本上这里看到xmm0就是栈对其问题了。出现问题原因很简单,linux系统一......
  • 【洛谷 P1271】【深基9.例1】选举学生会 题解(计数排序)
    【深基9.例1】选举学生会题目描述学校正在选举学生会成员,有名候选人,每名候选人编号分别从1到,现在收集到了张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。输入格式输入和以及个选票上的数字。输出格式求出排序后的选票编......
  • CTFpwnAD世界dice_game题解wp
    惯例checksec一下看看main首先seed函数用时间生成一个随机数,这个随机数做为srand函数的参数让srand函数生成一个种子。(这个种子会影响后面的rand函数生成结果,并且同样的种子会使rand函数生成同样的随机数,就是所谓的伪随机)以及看到这里会有连续五十轮游戏。sub_A20这里就是每一轮......
  • [ARC106F] Figures 题解
    题目链接点击打开链接题目解法这么神仙的推式子题看到生成树计数,第一反应是\(prufer\)序列考虑在\(prufer\)序列上搞这个东西可以得到\(ans=\sum\limits_{\sum\limits_{i=1}^nd_i=n-2}\binom{n-2}{d_1,d_2,...,d_n}\times\proda_i^{\underline{d_i+1}}\)考虑拆式子......
  • 问题解决
    howtomeasuressolutionsaddresstheimportanceofspeaking abilityandhowtodevelopit.Astherapid developmentofglobalization,itisofgreatnecessityforyoungstertoimproveourspeakingability.Howtoaddressthisproblem?Thefollowingsoluti......
  • AtCoder Beginner Contest 332 题解
    A-OnlineShopping题目链接AtcoderLuogu简要题意共有\(n\)件商品,第\(i\)件商品的价格为\(p_i\)日元,数量为\(q_i\)件。除了购买商品所需的的钱数,还要支付运费:如果所买商品的总价小于\(s\)日元,那么要支付运费\(k\)日元。问所需要的钱数是多少。简要思路模拟......
  • cdr 小问题解决方案
    1,插件卸载不干净1.1:插件自带的卸载1.2:点击cdr文件夹,选择路径CorelDRAWGraphicsSuiteX8\Draw\plugins64,删除其中所有的"*.cpg"文件(如果你安装了其他插件,这里也会有其他插件的cpg文件,请仔细辨认。或者直接全部删了,到时再安装一下你需要保留的插件)。 2,cdr矩形,对象属性无法更......