2025-4-26 模拟赛

T1

构建一个数据结构,维护一个长度为 \(n\) 的排列 \(a_1,a_2,\dots,a_n\),同时支持以下四种操作:

  • 给定下标 \(i\),将所有满足 \(a_j<a_i\)\(a_j\) 执行赋值操作 \(a_j\gets a_j+1\),最后执行赋值操作 \(a_i\gets 1\)
  • 给定下标 \(i\),将所有满足 \(a_j>a_i\)\(a_j\) 执行赋值操作 \(a_j\gets a_j-1\),最后执行赋值操作 \(a_i\gets n\)
  • 给定下标 \(i,j\),保证 \(i\neq j\),交换 \(a_i\)\(a_j\) 的值。
  • 给定区间 \(l,r\),保证 \(1\le l\le r\le n\),询问 \(\sum_{i=l}^r a_i\) 的值。

此时,永恒时空的诞生,要求这一数据结构具备“量子”特征,即修改操作会产生多个状态。具体而言,每次修改操作都会给出一个额外的参数 \(p\),该数据结构会将所有的当前状态都复制 \(M+1\) 份(其中 \(M=998244353\)),而其中的 \(p\) 份会执行当前操作,而另外的 \(M+1-p\) 份则不会执行当前操作,也即对 \(a\) 没有任何影响。也就是说如果当前修改操作之前有 \(c\) 个状态,则经历当前修改操作之后,状态总数将会变成 \(c\times(M+1)\)

因此,对于每次询问,该数据结构要求支持,得到所有的平行状态执行当前询问操作的答案的和。请你构建这样的数据结构。

时间限制 1 秒,空间限制 512 MB。

sol:

场上怎么只会最菜的暴力了。

⾸先操作等价于,将⼀段值域的前缀和后缀整体往反⽅向移动⼀个单位(场上未能发现)然后将值域上重叠的单点移到空缺的端点处。

在这个过程中注意到每次“量⼦操作”后会将原序列状态复制恰好 \(M+1\) 份,这是啥,这不是概率吗!

考虑 \(n\) 较⼩的情况,设 \(f(i,j)=P(\text{原序列中}a_i>a_j)\),显然 \(a_i=1+\sum_{j=1}^n f(i,j)\)

操作一将⼀个单点修改⾄值域左端,操作二将⼀个单点修改⾄值域右端,不改变序列中其他元素的偏序关系,然后操作就变成了容易搞定的单修。

然后考虑查询,查询操作就是求 \(\sum_{i=l}^r\sum_{j=1}^n f(i,j)\)

我们可以在修改过程中对于每个位置 \(i\) 动态的维护 \(g(i)=\sum_{j=1}^nf(i,j)\),然后就只要求 \(\sum_{i=l}^r g(i)\),这些可以 \(O(n^2)\) 搞定(\(n,q\) 同阶)

但是 \(n\le 10^5\),所以进行拓展。我们发现有很多区间没有被修改过偏序情况,所以视为一个整体。

使用离散化,把操作修改的划分点单独拉出来,然后划出小区间。然后设 \(f\{[l_1,r_1],[l_2,r_2]\}=\sum_{i=l_1}^{r_1}\sum_{j=l_2}^{r_2}f(i,j)\),维护方法同上。


T2

这个是原,具体题号忘了,之前见过,但是应该没写。

定义一个长度为 \(m\) 的序列 \(b_1,b_2,\dots,b_m\) 是好的,当且仅当可以将这个序列中的每一个元素分到两个非空集合中,使得第一个集合中的每个元素按位与的结果等于第二个集合中每个元素按位或的结果。

例如序列 \([1,7,3,11]\) 是好的,因为可以将该序列划分成 \(\{7,11\}\)\(\{1,3\}\),第一个集合按位与的结果为 \(3\),第二个集合按位或的结果同样为 \(3\)

给定一个长度为 \(n\) 的序列 \(a_1,a_2,\dots,a_n\),有 \(q\) 次询问,每次询问给定 \(l_i,r_i\),判断序列 \(a\) 的区间 \([l,r]\) 构成的序列 \(a_l,a_{l+1},\dots,a_r\) 是否是好的。

时间限制 1 秒,空间限制 1024 MB。

sol:

按位或只增不降,按位与只降不增。
考虑对于一个答案 \(x\)\(>x\) 的一定去第一个集合,\(<x\) 的一定去第二个集合,然后算前后缀和就搞定了,但是 \(O(nq\log n)\) 太慢。
于是对于答案的位数分个类,设 \(x\) 二进制里有 \(k\)\(1\),个数 \(>k\) 的一般去第一个集合,\(<k\) 的一定去第二个集合,\(=k\) 的一般去第二个集合。
然后特例情况是所有个数 \(=k\) 的按位或 \(=\) 所有个数 \(>k\) 的按位与,并且所有个数 \(=k\) 的至少有 \(2\) 个且都相同,check 一下就写完了。

开两组每组 30 个 st 表存个数 \(=k\) 的区间按位与和按位或,时间复杂度双 \(\log\),跑的挺快。

#include<bits/stdc++.h>
using namespace std;
#define ppc __builtin_popcount
int n,m,a[100005],rk[100005];
int cnt[32][100005],st1[32][18][100005],st2[32][18][100005];
int to[32],ta[32],tc[32];
// 2^30-1
// 31-
// 1<<30=1073741824
int qry1(int id,int l,int r){//and
	int len=log2(r-l+1);
	return st1[id][len][l]&st1[id][len][r-(1<<len)+1];
}
int qry2(int id,int l,int r){//or
	int len=log2(r-l+1);
	return st2[id][len][l]|st2[id][len][r-(1<<len)+1];
}
signed main(){
//	freopen("b4.in","r",stdin);
//	freopen("test.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		cnt[ppc(a[i])][i]=1;
	}
	for(int d=0;d<31;d++)for(int i=1;i<=n;i++)cnt[d][i]+=cnt[d][i-1];
	for(int d=0;d<31;d++){
		for(int i=1;i<=n;i++){
			if(ppc(a[i])==d)st1[d][0][i]=st2[d][0][i]=a[i];
			else st1[d][0][i]=1073741823,st2[d][0][i]=0;
		}
		for(int i=1;(1<<i)<=n;i++){
			for(int j=1;j<=n-(1<<i)+1;j++){
				st1[d][i][j]=st1[d][i-1][j]&st1[d][i-1][j+(1<<i-1)];
				st2[d][i][j]=st2[d][i-1][j]|st2[d][i-1][j+(1<<i-1)];
			}
		}
	}
	while(m--){
		int l,r;cin>>l>>r;
		for(int i=0;i<=30;i++){
			ta[i]=qry1(i,l,r);
			to[i]=qry2(i,l,r);
			tc[i]=cnt[i][r]-cnt[i][l-1];
			if(i)to[i]|=to[i-1],tc[i]+=tc[i-1];
		}
		for(int i=29;i>=0;i--)ta[i]&=ta[i+1];
		bool flg=0;
		for(int i=0;i<=30;i++){
			if(i<30&&to[i]==ta[i+1]&&tc[i]&&r-l+1!=tc[i])flg=1;
			if(cnt[i][r]-cnt[i][l-1]>1&&to[i]==ta[i])flg=1;
			if(flg){
				cout<<"YES"<<'\n';
				break;
			}
		}
		if(!flg)cout<<"NO"<<'\n';
	}
	return 0;
} 

upd:被同学查出来原题了,P10743


T3

定义一个无向图 \(G\) 的线图 line graph 变换为:对于点集 \(V\),边集 \(E\) 的无向图 \(G\),该图的线图 \(L(G)\) 也是一个无向图:

  • \(L(G)\) 的点集大小为 \(|E|\),每个点唯一对应着原图的一条边。
  • 两个点之间有边当且仅当这两个点对应的边在原图上有公共点(注意不会存在自环)。

比较容易注意到,无向图 \(G\) 经过若干轮线图变换后,其点数和边数可能会呈指数级别的增长。

给定一个无向图 \(G\),询问该线图 \(L^k(G)\) 的最大独立集大小,答案对 \(998244353\) 取模即可。

时间限制 1 秒,空间限制 1024 MB。\(k\le 7,n,m\le 2000\)

sol:

计数题,场上只会 \(k\le 5\) 的做法。

手玩一点小样例,发现线图由若⼲个团构成,因此 \(k\) 阶线图的最⼤独⽴集就等价于\(k-1\) 阶线图的最⼤匹配。注意到线图的连通性质非常强大!发现原图中⼀个连通块不会在线图中被分裂成两个连通块。

然后我们来一个一个看。

\(k=2\):对于原图的⼀个连通块,取出该连通块的⼀棵 dfs 树,则可以简单构造达到最⼤匹配的上界,因此对于⼀个有 \(m\) 条边的连通块,其最⼤匹配数量等于 \(\lfloor \frac{m}{2}\rfloor\)
\(k=3\):考虑⼀个连通块在⼆阶线图中的边数,容易得到 \(ans=\sum_{i=1}^n\binom{deg_i}{2}\)
\(k=4\):考虑⼀个连通块在三阶线图中的边数,手玩一些样例,找一下规律有 \(ans=\sum_{(u,v)\in E}\binom{deg_u+deg_v-2}{2}\)
\(k=5\):无法手玩,于是换一个计数方法。考虑贡献,在原图上统计产⽣贡献边的⼦图形态。可以发现这样统计将容易控制,只需要分析所有由四条边构成的连通块的形态的贡献,可以容斥,系数比较简单(都是整数)
\(k=6\):发现 \(k=5\) 的情况可以将统计放在点上进⾏,因此把 \(k=5\) 的贡献分析放在边上进⾏就是 \(k=6\)
\(k=7\):没法算了,但是发现 \(n,m\le 2000\),而前面的东西都是 \(O(n+m)\) 的。所以直接建一阶线图,然后跑 \(k=6\) 就解决了。

posted @ 2025-04-26 12:02  Xuan_tmp  阅读(27)  评论(0)    收藏  举报