国庆 Daimayuan 模拟赛总结

Day 7

开题顺序好重要啊!

复盘

8:00 开题,没有通览一遍,想试试看一道想一道的策略

翻译了一下 T1 的条件,把 or 的性质想错了;往下数位 dp 是好想的,但需要记录进位?结合那个错误的条件发现不得不子集枚举,复杂度不对

尝试了好久能不能把子集枚举魔改成高维前缀和,最终失败。准备开码那个思路时重新审了一下题,发现理解错了,根本不会有进位,那dp就简单多了

码完 9:50,好在样例都一遍过了。这时间很失败啊

看 T2,想到一个树形结构很适合来刻画这个问题,考虑叶子到根的距离,决定了某个变量的贡献是正还是负

但 dp 过程中显然无法记录树形态,去看特殊性质也没什么好写的,蚌

看了眼 T3 发现是构造,心想不会和之前某次 T2 构造一样特别难吧,跳了

看 T4,第一印象还不错,发现 操作 1,2 就是点分树板子,但很显然点分树是没办法处理子树的,往下看部分分,这一档只有 20,性价比不高

发现 n q nq nq 暴力比较好拿,再往下写个无脑线段树能再拿 10,再看 v = 0 v=0 v=0 有 20?

然后开始编,成功编出值域线段树做法,看了眼时间已经 11:00 了,决定还是码完暴力分去看 T2

仔细分析了一下,发现由于元素是任意选的,那么答案一定可以刻画成形如 ( a , b , c ) (a,b,c) (a,b,c) 的三元组,表示 a a a 个正号, b b b 个负号, c ∗ K c*K cK

感觉这个思路很对,继续想可以得到一个大概是 n 3 n^3 n3 的暴力 dp:直接暴力求出来所有合法三元组

尝试打表出来,发现这些三元组竟然是十分有规律的,可以 O ( 1 ) O(1) O(1) 算的那种

然后就发现会了正解:直接求出来其中的一个三元组,剩下的可以快速得到。对于多组询问,直接离线就好了

看了眼时间 11:45,逆天

写完 n q nq nq 的已经 11:55,看到有 65pts,可惜最后正解没写出来

结果是

100 + 65 + 0 + 10 = 175 , rk_49 唉

T1 有点唐了,碰到感觉很麻烦的 T1 还是应该多审审题的

T2 应该能写出来的

T3 真应该看的, n 2 n^2 n2 的思路并不难想

T4 积累到一个 BFS 序处理邻域问题的思路

题解

T4 还没订,正解有个地方不太懂,回来补

Day 8

难蚌的一场

复盘

这波采取了先看完四道题的策略,感觉 T1 还是很典,T2 像是比较套路的题,应该能做;T3 很逆天,不太会;T4 更逆天

看 T1,数据范围明显是让往贡献一次计算好的角度思考的,很快有了 n^4 的做法,但是 1 s 1s 1s 能跑 1 e 9 1e9 1e9 吗?

磕绊了一会,没什么更好的思路了,决定开写。

打表发现约束完上下界后单次询问只会循环 8 e 6 8e6 8e6 次,这不妥妥赢嘛!

9:00 调完交了,过掉了大样例,跑的飞快

开 T2,想了很久觉得不太有什么 log 做法,那么对出现次数根分的思路就很明显了

然鹅 c n t > n cnt>\sqrt n cnt>n 的计算方式想的有点垃圾,十分难以拓展(需要把求相交的容斥一步变成求包含);导致 c n t < n cnt<\sqrt n cnt<n 的即使想到 ∑ c n t 2 ≈ n n \sum cnt^2≈n\sqrt n cnt2nn 的枚举数对做法,依然有很多限制

想了将近 2h,最后无奈暴力

中间 T3 又扫了一眼,对第一个特殊性质都没想出很好的做法,感觉是心有点慌,没静下心去手玩,其实前几档都不是很难

最后剩不到 1h 看 T4 了,对于两矩形不交,只要存在一维不交就行;但相交的话需要每一维都交,显然容斥后是更好做的,这样可以使得情况与 k k k 无关,只需要直接 k k k 次方就行

到底容斥的是什么呢?不应该是”某几个矩形交“这样笼统的钦定,这么答案永远算不对,容斥的本质还是对关系钦定

考虑一张 6 6 6 个点的图,两点连边表示钦定二者相交,这么一来有 n ( n − 1 ) 2 = 15 \frac{n(n-1)}{2}=15 2n(n1)=15 个关系,对这样的关系钦定

然后问题在于方案数怎么求,想了好久没什么正常的 dp 思路,最后发现可以直接 dfs !应该能做 c ≤ 10 c\leq10 c10 的,加上别的有 60 pts

开写!最后 11:59:50 极限过掉样例交了

结果是:

100 + 30 + 0 + 25 = 155 , rk_41

T2 开始想的有点偏了,应该尝试换种计数方式的,剩下的确实是比较套路的做法

T4 算错复杂度了,感觉 4 5 n 45^n 45n 应该 n n n 多大都不会超,没想到只能跑 n = 4 n=4 n=4。顺着赛时思路往下想,很快就想到了 c = 1 e 9 c=1e9 c=1e9 可以离散化的 。。。

已经差不多推到正解了,接下来就是对搜索的一些剪枝技巧或者直接打表,让它不 TLE

T3 这种构造还是应该静下心去手玩一下的…

题解

T3 T4 没订,T4 调了调赛时代码把 n = 4 n=4 n=4 跑过了

Day 9

省流:被 T2 随机区分了

复盘

8:00 开题,还是扫了一遍四道题,T1 看上去不难,T2 想了想感觉不太好做;T3 挺神秘的;T4 数据结构?

简单推了下性质,发现最终每一段取值是能定下来的,然后感觉每一段固定不下来,贪心似乎不太对?就写了个 dp ,发现很好优化,用 st 表维护区间 and 然后双指针即可。1h 才过掉

T2,慢慢推性质,无解很好判,倒过来做就行;然后发现答案要么 n+m ,要么某行或者某列没涂色,先假设做行,列的情况是对称的

枚举没涂色的行,可以把列的状态都确定下来,接下来一行行比对,给列加一些限制

发现限制有两种:01\10 无解限制,顺序限制

前者直接扫,后者发现需要建图跑个 toposort,额,好难写啊!

这个思路应该很对,但复杂度是 n 3 n^3 n3 的,想了想应该十分跑不满,写写看

怒写 1.5h 多,5k,过掉了小样例,感觉正确性应该没问题(如果没写挂),过了

开 T3,发现其实很水,暴力的 dp 写完后转移就是一个二维偏序,树状数组维护之,20min 就写完了

抓紧时间看 T4,从本题性质的角度出发,发现 k=1 的倍增做法很简单,尝试拓展到多个区间就不会做了

想了好久也没什么进展,决定再看看离线能不能做。好吧,也不会

最后写暴力,看到有 n = 5 e 4 , 1 e 5 n=5e4,1e5 n=5e4,1e5 想试试 n 2 n^2 n2 能不能冲过去,然后就想到一个很简洁的暴力思路:每次查一个点的父亲是否被标记过,然后标记它

写完发现果然过了 n = 7 e 4 n=7e4 n=7e4 的样例,果然是小常数选手

然后就结束了

结果是:

100 + 0 + 100 + 40 = 240 , rk_36

诶,这 T2,样例给的这么水还是一道细节多(我的做法)题,应该多手玩几组样例 hack 一下的,但没想到真直接挂完了

赛后简单调一下就有 70 了…

然而赛时还是应该多想想的,仔细分析发现 toposort 的限制其实是不用考虑的,只需要在开头判无解就行。这样就复杂度又低细节又少了

T4 其实可以先想暴力的,赛时最后打暴力时才发现了 只需要考虑父亲是否在当前区间出现过 即可,那么接下来根号分治的思路就比较自然了,这可以说是比较套路的做法

正解有点牛啊!从那个 k=1 的拓展,结合树上的性质得到的做法

题解

T4 已听懂,还没写完

Day 10

节奏比较好的一场

复盘

决定换一下策略,读题、想题,有思路后不急着写代码,四道题都能拿到一些分数后再开写

8:00 开题,看到 T1 题面贼长,感觉很神秘;T2 又是构造,不过感觉可做;T3 题面好抽象啊,手推样例虽然能推出来,但结合题面看还是感觉很别扭;T4 感觉很逆天,不过想了想 60pts 是挺好拿的

回看 T1 发现挺诈骗, R × C ≤ 2.5 × 1 0 5 R\times C\leq 2.5\times 10^5 R×C2.5×105 ,直接暴力染色复杂度是对的,写的 s e t set set 分段做,细节还是挺多的,9:00 交了

开 T2,容易观察出 + n , − n +n,-n +n,n 不影响答案,可以在 m o d   n mod\ n mod n 意义下做;然后是绝对值,那么不妨先钦定 b n = 0 b_n=0 bn=0,前面的数就都是 ± d i \pm d_i ±di 了,然后跑个背包,限制是要把最小的 − b i -b_i bi 加成正数,那么记录一下和的最小值就行

需要考虑最小的 b i b_i bi 取到哪,考虑 sort 完后从大到小往背包里加数,同时统计答案。细节不多,10:00 过了样例

看 T3,不懂这个换人的过程,一直没有很好的 poly 做法,猜了个东西,感觉不是很真。想了半个小时跳了,决定先拿 T4 60pts

n 4 n^4 n4 很好写,对于新加一条边, f l o y d floyd floyd 不用重新跑,只枚举点对即可;对于树的情况推了一会,还是 n 2 n^2 n2 枚举的思路,但计算贡献可以加速到 O ( n ) O(n) O(n)

接着继续推正解,下意识觉得不太可能是这种暴力 n 2 n^2 n2 枚举边然后 check 的思路,应该是结合什么性质直接把加边给确定下来

于是打表,猜了很多结论,都没法做。只能先写了

11:30 写完了,赶紧看 T3。又想了好久觉得还是用那个猜的结论写写吧,最后 10min 写完,发现过不去样例,就 gg 了

结果是

100 + 0 + 0 + 60 = 160 , rk_48

难蚌,T2 有个递归边界以为不用写的,没想到被 n = 2 n=2 n=2 的数据给卡了,只有这一种才能卡掉,改改就过了

赛后才发现 T3 改题面了,把那个抽象的过程描述的清晰多了,然后按题意模拟着 dp 就能有一个 n 3 n^3 n3 做法,蚌

T4 正解还是从暴力 n 2 n^2 n2 枚举出发的,数据范围小的时候还是应该往这方面想想的

不过还是感觉这把策略比较好,前面推完就知道后面哪些题好拿分了

题解

已订完

T2

在这里插入图片描述
妙妙的题,不过推出来了

T3

在这里插入图片描述
好牛的题啊!

首先看完修改后的题面,我们按题意设计一个 dp : f i , j , k f_{i,j,k} fi,j,k 表示 p p p 中考虑前 i i i 个, q q q 中考虑前 j j j 个,冲突了 k k k 个的方案数,显然对于第三维我们只关注数量即可,复杂度 O ( n 3 ) O(n^3) O(n3)

	f[x][y][cnt] = 1 ;
	LL ans = 0 ;
	for(int i = x ; i <= n ; i ++ ) {
		for(int j = y ; j <= n ; j ++ ) {
			for(int k = min(i,j) ; k >= 1 ; k -- ) {
				if( f[i][j][k] == 0 ) continue ;
				if( pos2[p[i+1]] <= j ) f[i+1][j][k] = ( f[i+1][j][k] + f[i][j][k] ) % mod ;
				else f[i+1][j][k-1] = ( f[i+1][j][k-1] + f[i][j][k] ) % mod ;
				if( pos1[q[j+1]] <= i ) f[i][j+1][k] = ( f[i][j+1][k] + f[i][j][k] ) % mod ;
				else f[i][j+1][k-1] = ( f[i][j+1][k-1] + f[i][j][k] ) % mod ;
			}
			ans = ( ans + f[i][j][0] ) % mod ;
		}
	}

进一步观察 打表,当 i , j i,j i,j 固定时, k k k 实际上也是固定的。从这个方案构造的过程我们就能得出这一点

有: k = [ 前 i 与前 j 中冲突的个数 ] − ( i − x ) − ( j − y ) k=[前 i 与前 j 中冲突的个数] - (i-x) - (j-y) k=[i与前j中冲突的个数](ix)(jy) ,实际上这个是比较好观察的,我们把这个设为 k ( i , j ) k(i,j) k(i,j)

然后我们 d p dp dp 只记两维即可, f i , j f_{i,j} fi,j,此时转移变成了:

f i , j { → a n s , k ( i , j ) = 0 → f i + 1 , j , k ( i , j ) > 0 → f i , j + 1 , k ( i , j ) > 0 f_{i,j}\left\{\begin{matrix}\to ans , k(i,j)=0 \\\to f_{i+1,j},k(i,j)>0 \\\to f_{i,j+1},k(i,j)>0 \end{matrix}\right. fi,j ans,k(i,j)=0fi+1,j,k(i,j)>0fi,j+1,k(i,j)>0

进一步优化:dp 方程显然是一个典型的格路计数!

( x , y ) (x,y) (x,y) 开始,每次向右或向上,走到 k ( i , j ) = 0 k(i,j)=0 k(i,j)=0 的位置就停下并贡献到答案中

还是没法直接做,分析一下性质

k ( i − 1 , j ) ≥ k ( i , j ) ≥ k ( i − 1 , j ) − 1 k(i-1,j)\geq k(i,j)\geq k(i-1,j)-1 k(i1,j)k(i,j)k(i1,j)1

意思是:当 i i i 往后移动一步,冲突的数量要么不变,要么减少 1 1 1。对于 j j j 同理

这告诉我们 k ( i , j ) k(i,j) k(i,j) 具有单调性!画个图

在这里插入图片描述
1 1 1 代表 k ( i , j ) k(i,j) k(i,j) 0 0 0 的位置

这样我们只需双指针求出外面的一圈终点的坐标,然后方案直接组合数算,显然终点数是 O ( n ) O(n) O(n)

注意到一个 0 0 0 的答案要减掉 到左边 0 0 0 和 到下边 0 0 0 的方案 (到 0 0 0 就停下)

牛啊

T4

在这里插入图片描述
看数据范围, n n n 最大只有 600 600 600,那么我们可以考虑 n 2 n^2 n2 枚举后计算减量(还有一点是因为去图上找性质真发现不了什么)

n 2 n^2 n2 的计算是简单的,注意 f l o y d floyd floyd 加入一条新边或一个新点只需要 n 2 n^2 n2 枚举点对更新就行

然后考虑优化这个十分暴力的过程,设 f ( a , b ) f(a,b) f(a,b) 表示新加入 ( a , b ) (a,b) (a,b) 这条边之后贡献的减量,那么: f ( a , b ) = ∑ p , q m a x ( 0   ,   d ( p , q ) − d ( p , a ) − d ( b , q ) − 1   ,   d ( p , q ) − d ( p , b ) − d ( a , q ) − 1 ) f(a,b)=\sum_{p,q}max(0\ ,\ d(p,q)-d(p,a)-d(b,q)-1\ ,\ d(p,q)-d(p,b)-d(a,q)-1) f(a,b)=p,qmax(0 , d(p,q)d(p,a)d(b,q)1 , d(p,q)d(p,b)d(a,q)1)

m a x max max 中有三个式子,很难同时维护;如果后两个式子都 > 0 >0 >0 的话比较它们的大小是不容易的

我们有一个很妙的结论:后两个式子不能同时大于 0 0 0

在这里插入图片描述

换句话说,加入 ( a , b ) (a,b) (a,b) 后,黄色路径和绿色路径不可能都比原来的 d ( p , q ) d(p,q) d(p,q)

反证法:

加入之前, d ( p , q ) d(p,q) d(p,q) 显然可以走 p → a → q p\to a\to q paq,这条路径比黄色路径长,可以得到: m < y + 1 m<y+1 m<y+1

d ( p , q ) d(p,q) d(p,q) 也可以走 p → b → q p\to b\to q pbq,这条比绿色路径长,那么 y < m + 1 y<m+1 y<m+1

显然矛盾

( 这种结论还是记一下吧

那么我们就可以把 m a x max max 给拆开了,设 g ( a , b ) = ∑ p , q m a x ( 0   ,   d ( p , q ) − d ( p , a ) − d ( b , q ) − 1 ) g(a,b)=\sum\limits_{p,q}max(0\ ,\ d(p,q)-d(p,a)-d(b,q)-1) g(a,b)=p,qmax(0 , d(p,q)d(p,a)d(b,q)1)

那么 f ( a , b ) = g ( a , b ) + g ( b , a ) f(a,b)=g(a,b)+g(b,a) f(a,b)=g(a,b)+g(b,a),直观的理解:加入无向边减少的量,等于分别按两个方向经过减少量的和

考虑怎么求 g ( a , b ) g(a,b) g(a,b),四个变量,常见优化思路是 把这些变量分成无关的部分,每个部分预处理,然后合并

g ( a , b ) = ∑ p , q m a x ( 0   ,   d ( p , q ) − d ( p , a ) − d ( b , q ) − 1 ) g(a,b)=\sum\limits_{p,q}max(0\ ,\ d(p,q)-d(p,a)-d(b,q)-1) g(a,b)=p,qmax(0 , d(p,q)d(p,a)d(b,q)1)

考虑枚举 b , p b,p b,p,把式子改成

∑ p , q m a x ( 0   ,   d ( p , q ) − d ( b , q ) − ( d ( p , a ) + 1 )   ) \sum\limits_{p,q}max(0\ ,\ d(p,q)-d(b,q)- (d(p,a)+1)\ ) p,qmax(0 , d(p,q)d(b,q)(d(p,a)+1) )

X p , b , q = d ( p , q ) − d ( b , q ) X_{p,b,q}=d(p,q)-d(b,q) Xp,b,q=d(p,q)d(b,q)

发现前后两部分是独立的,考虑对 X p , b X_{p,b} Xp,b d ( p , a ) + 1 d(p,a)+1 d(p,a)+1 分别排序,双指针求刚好 ≥ \geq 的位置,前缀和计算之

排序不能 s o r t sort sort,这样是 n 3 log ⁡ n n^3\log n n3logn 的,改成桶排就 ok 了

#include<bits/stdc++.h>
using namespace std ;

typedef long long LL ;
const int N = 610 ;

int n , m ;
vector<int> E[N] ;
int d[N][N] , ans , X[N] , sum[N] , g[N][N] ;
int id[N] , P ;
bool cmp( int x , int y )
{
	return d[P][x] < d[P][y] ;
}
int cnt[N] ;

int main()
{
	scanf("%d%d" , &n , &m ) ;
	int x , y ;
	memset( d , 0x3f , sizeof d ) ;
	for(int i = 1 ; i <= n ; i ++ ) d[i][i] = 0 , id[i] = i ;
	for(int i = 1 ; i <= m ; i ++ ) {
		scanf("%d%d" , &x , &y ) ;
		d[x][y] = d[y][x] = 1 ;
		E[x].push_back(y) ;
		E[y].push_back(x) ;
	}
	for(int k = 1 ; k <= n ; k ++ ) {
		for(int i = 1 ; i <= n ; i ++ ) {
			for(int j = 1 ; j <= n ; j ++ ) {
				d[i][j] = min( d[i][j] , d[i][k]+d[k][j] ) ;
			} 
		}
	}
	ans = 0 ;
	for(int i = 1 ; i <= n ; i ++ ) {
		for(int j = i+1 ; j <= n ; j ++ ) ans += d[i][j] ;
	}
	int res = 0 ;
	for(int p = 1 ; p <= n ; p ++ ) {
		P = p ;
		sort( id+1 , id+n+1 , cmp ) ;
		for(int b = 1 ; b <= n ; b ++ ) {
			for(int q = 1 ; q <= n ; q ++ ) {
				X[q] = d[p][q]-d[b][q] ;
				if( X[q] >= 1 ) cnt[X[q]] ++ ;
			}
			int sum = 0 , ct = 0 ;
			for(int i = n , j = n+1 ; i >= 1 ; i -- ) {
				int a = id[i] ;
				while( j-1 >= 1 && j-1 > d[p][a]+1 ) {
					sum += (j-1)*cnt[j-1] ;
					ct += cnt[j-1] ;
					j -- ;
				}
				g[a][b] = ( g[a][b] + sum-(d[p][a]+1)*ct ) ;
			}
			for(int j = 1 ; j <= n ; j ++ ) cnt[j] = 0 ;
		}
	}
	for(int a = 1 ; a <= n ; a ++ ) {
		for(int b = a+1 ; b <= n ; b ++ ) {
			res = max( res , g[a][b]+g[b][a] ) ;
		}
	}
	int num = 0 ;
	for(int a = 1 ; a <= n ; a ++ ) {
		for(int b = a+1 ; b <= n ; b ++ ) {
			if( res == g[a][b]+g[b][a] ) num ++ ;
		}
	}
	printf("%d %d\n" , ans-res/2 , num ) ; 
	return 0 ;
}

Day 11

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值