7.23模拟赛总结 [数据结构优化dp] + [神奇建图]

news2024/11/25 4:54:00

目录

  • 复盘
  • 题解
    • T2
    • T4

复盘

浅复盘下吧…

7:40 开题

看 T1 ,起初以为和以前某道题有点像,子序列划分,注意到状态数很少,搜出来所有状态然后 dp,然后发现这个 T1 和那个毛关系没有

浏览了一下,感觉 T2 题面又臭又长,意思也很恶心;T3 树上 ds 看上去很亲切;T4 一眼就不太可做

回来看 T1,发现很 sb,每次肯定贪心选最优的后缀,至于选 m 的限制,填满一段后再贪心往前选就行

8:04 码完了,小样例顺利过掉,一测大样例发现小数点后面不对,想了想应该不会是精度问题,可能做法假了

然后 不断证明结论+修改一些毫无影响的细节,仍然和大样例不上,最后决定把题面重读一遍,知道看到了 “相对误差”,6,突然想到我学过高中物理。。。到 8:50 才交上去

快开 T2,朴素的想法当然是 二维状态记 Max,但这个显然不太有优化空间(这种状态设计只有 i − 1 i-1 i1 i i i 只有 O ( 1 ) O(1) O(1) 个决策需要单点修改时才能优化)

那么很快想到改成 f i f_i fi 一维状态,钦定 i i i 必选,往前找一个合法的,发现可以接上去的区间可以预处理出来,那么只需找 [ l , r ] [l,r] [l,r] 内小于 a i a_i ai 的最优决策… 三维偏序?树套树警告!

算了,先打暴力,竟然有 O ( 1 ) p t s O(1) pts O(1)pts 的高分,然鹅被一个 sb 细节卡住一直到 9:30 仍没调过,决定先看 T3

一眼发现是 sb 题,直接树上主席树就做完了,直接决定开码,10:30 过了小样例

然鹅大样例又挂了,反复调根本不明白怎么回事,一度以为自己主席树板子假了

最后突然想着把数组开大一倍,卧槽对了,不爆 RE 直接 WA 是吧,浪费了高达 O ( n ) O(n) O(n) 的时间

11:00 了,先把 T1 暴力调了吧,发现弱智错误… 然后看看能不能写点性质,得到了高达 5 p t s 5pts 5pts 的性质分

最后想 T2 感觉写不完,决定开 T4 暴力

最后获得了高达 7 p t s 7pts 7pts 的暴力分,赢!

所以 100+53+100+7=260 , rk O ( 2 n ) O(2^n) O(2n)

题解

T2

在这里插入图片描述
在这里插入图片描述
其实离正解不远了,回顾一下转移:

f i = m a x ( f j + 1 ) f_i=max(f_j+1) fi=max(fj+1),其中 j < i , a j < a i j<i,a_j<a_i j<i,aj<ai i , j i,j i,j 可以通过小于 a i a_i ai 的数 “连接” 起来

直接三维偏序做也没错,但是本题可以有更多性质

注意到:能转移的决策满足 a j < a i a_j<a_i aj<ai,能连接其它数的数也是 a j < a i a_j<a_i aj<ai ,二者可以同时维护

那么我们转到值域上做,从小到大插入新决策

每次处理询问时相当于要找连续段,这个可以 s e t set set 做(更好做法是并查集,但是我不会);然后询问区间 Max,线段树维护

遇到偏序问题可以尝试 在最外层换一维关键字排序,会有意想不到的效果

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

typedef long long LL ;
const int N = 3e5+100 ;

int n , D , a[N] ;
int f[N] , rhk[N] ;
struct Segtree
{
	int l , r , Max ;
}t[4*N] ;
bool cmp( int x , int y )
{
	return a[x] < a[y] ;
}
void build( int p , int l , int r )
{
	t[p].l = l , t[p].r = r ;
	if( l == r ) {
		return ;
	}
	int mid = ( l + r ) >> 1 ;
	build( p<<1 , l , mid ) ; build( p<<1|1 , mid+1 , r ) ;  
}
int ask( int p , int l , int r )
{
	if( l <= t[p].l && t[p].r <= r ) {
		return t[p].Max ;
	}
	int mid = ( t[p].l + t[p].r ) >> 1 , Max = 0 ;
	if( l <= mid ) Max = max( Max , ask(p<<1,l,r) ) ;
	if( r > mid ) Max = max( Max , ask(p<<1|1,l,r) ) ;
	return Max ;
}
void modify( int p , int x , int d )
{
	if( t[p].l == t[p].r ) {
		t[p].Max = max( t[p].Max , d ) ;
		return ;
	}
	int mid = ( t[p].l + t[p].r ) >> 1 ;
	if( x <= mid ) modify( p<<1 , x , d ) ;
	else modify( p<<1|1 , x , d ) ;
	t[p].Max = max( t[p<<1].Max , t[p<<1|1].Max ) ;
}
struct node
{
	int l , r ;
	friend bool operator < ( node x , node y ) {
		return x.r < y.r ;
	}
};
set<node> s ; // 维护连续段 
int query( int x ) // 查 x 可用决策 
{
	int P = max(1,x-D) ;
	auto it = s.lower_bound((node){0,P}) ;
	if( it == s.end() ) {
		return 0 ;
	}
	return ask( 1 , min(it->l,P) , x-1 ) ;
}
void Insert( int x )// 插入决策 x 
{
	modify( 1 , x , f[x] ) ;
	if( s.empty() ) {
		s.insert((node){x,x}) ;
		return ;
	}
	auto it = s.lower_bound((node){0,x}) ;
	int L = x , R = x , fg = 0 ;
	if( it != s.end() ) {
		if( x < it->l ) {
			if( x+D >= it->l ) {// 接上了
				R = it->r ;
				fg = 1 ;
			} 
			if( it != s.begin() ) {
				auto iit = it ;
				iit -- ;
				if( iit->r + D >= x ) {
					L = iit->l ;
					s.erase( iit ) ;
				}
			}
			if( fg ) s.erase( it ) ;
			s.insert((node){L,R}) ;
		}
		return ;
	}
	it -- ;
	if( it->r+D >= x ) {
		L = it->l ;
		s.erase( it ) ;
	}
	s.insert((node){L,x}) ;
}

int main()
{
	scanf("%d%d" , &n , &D ) ;
	for(int i = 1 ; i <= n ; i ++ ) {
		scanf("%d" , &a[i] ) ; 
		rhk[i] = i ;
	}
	// 转移有两维限制,按值域做,去掉一维
	sort( rhk+1 , rhk+n+1 , cmp ) ;
	build( 1 , 1 , n ) ;
	int ans = 0 ;
	for(int i = 1 ; i <= n ; i ++ ) {
		int j = i ;
		f[rhk[i]] = query( rhk[i] ) + 1 ;
		while( j+1 <= n && a[rhk[j]] == a[rhk[j+1]] ) {
			j ++ ;
			f[rhk[j]] = query( rhk[j] ) + 1 ;
		}
		for(int k = i ; k <= j ; k ++ ) {
			Insert( rhk[k] ) ;
		}
		i = j ;
	}
	for(int i = 1 ; i <= n ; i ++ ) {
		ans = max( ans , f[i] ) ;
	}
	printf("%d" , ans ) ;
	return 0 ;
}

其实很好写

T4

神奇题
在这里插入图片描述
尝试 d p dp dp ,发现根本做不了…

根据我们的经验,遇到十分之抽象且题面又臭又长又不知所云的题目大多是图论,所以这题考虑建图

老师讲的一个建图出发点:注意到最终序列中每个值 要么由 a a a 提供,要么由 b b b,这种 “由 A 或由 B” 的问题是有二分图的样子的,考虑分左右两部,对于每个 i i i,将左部 a i a_i ai 与 右部 b i b_i bi 连边

我理解的:题目中给的 划分 实际上约束是很多的,我们考虑最初选所有 a a a 中的集合,然后用 b b b 中的若干个集合替换,这样 替换者的并 和 被替换者的并 必须是一样的,想换掉某个子集 a [ ] a[] a[] 的话,必须选择 所有 包含 b b b 中对应位置 的区间,然后对应回来 a a a 中区间也必须选… 如此往复(口胡)

我们尝试形式化的去描述这个东西,发现正可以用上面那种建边方式来描述 ,一个连通块就代表了 可以相互替换的一组 a [ ] , b [ ] a[],b[] a[],b[]

对于 K = 0 K=0 K=0,我们直接对于每个连通块取较小的那一组替换

对于 K = 1 K=1 K=1,考虑枚举边,分讨一下:

若断的是非割边,然后连到另一个连通块,这样贡献的变化是 m i n ( a , b ) + m i n ( c , d ) → m i n ( a + c , b + d ) min(a,b)+min(c,d)\to min(a+c,b+d) min(a,b)+min(c,d)min(a+c,b+d)

显然有不等式 m i n ( a , b ) + m i n ( c , d ) ≤ m i n ( a + c , b + d ) min(a,b)+min(c,d)\leq min(a+c,b+d) min(a,b)+min(c,d)min(a+c,b+d),所以贡献不会变小,断开一定不优

这个不等式也告诉我们,要尽可能拆连通块,尽可能不合并连通块

若断割边,我们最好的当然是连回本身,只拆,不合并

注意!这里有一个 conner,如果一个连通块只有两个节点 u , v u,v u,v 怎么办?我们显然没办法把 u u u 向自己连边

然而有这么一个事情:不妨设 u u u 为左部点,那么一定可以把 u u u 连到一个 左部点数不小于右部点的连通块上(找不到的话考虑右部点 v v v ),当 n ≥ 1 n\geq 1 n1 时,这样的连通块一定能找到

n = 1 n=1 n=1,直接特判 答案为 1 1 1 即可

对于 K = 2 K=2 K=2,与上面相反,需要 尽可能合并连通块,尽可能不拆连通块

对于一个连通块,如果有 非割边 ,那么用它一定比用割边更优,因为不会拆,且能够合并

下面考虑应该和哪个连通块合并,对于两个连通块 ( a 1 , b 1 ) (a_1,b_1) (a1,b1) , ( a 2 , b 2 ) (a_2,b_2) (a2,b2)

a 1 < b 1 , a 2 < b 2 a_1<b_1,a_2<b_2 a1<b1,a2<b2 (不等号方向相同):

贡献变化 m i n ( a 1 + a 2 , b 1 + b 2 ) − m i n ( a 1 , b 1 ) − m i n ( a 2 , b 2 ) = 0 min(a_1+a_2,b_1+b_2)-min(a_1,b_1)-min(a_2,b_2)=0 min(a1+a2,b1+b2)min(a1,b1)min(a2,b2)=0,没影响

a 1 < b 1 , a 2 > b 2 a_1<b_1,a_2>b_2 a1<b1,a2>b2 (相反)

贡献变化 m i n ( a 1 + a 2 , b 1 + b 2 ) − m i n ( a 1 , b 1 ) − m i n ( a 2 , b 2 ) min(a_1+a_2,b_1+b_2)-min(a_1,b_1)-min(a_2,b_2) min(a1+a2,b1+b2)min(a1,b1)min(a2,b2)

= m i n ( a 1 + a 2 , b 1 + b 2 ) − a 1 − b 2 =min(a_1+a_2,b_1+b_2)-a_1-b_2 =min(a1+a2,b1+b2)a1b2
= m i n ( a 2 − b 2 , b 1 − a 1 ) =min(a_2-b_2,b_1-a_1) =min(a2b2,b1a1)
= m i n ( Δ 1 , Δ 2 ) =min(\Delta_1,\Delta_2) =min(Δ1,Δ2)

a 1 , b 1 a_1,b_1 a1,b1 确定时,要找一个不等号相反,且差最大的,直接扫一遍记 Max 就行

如果全是割边,我们直接遍历这棵缩点后的树,依次断开每条树边即可

不太好写

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

typedef long long LL ;
const int N = 2e5+100 ; 

int T , K , M1 , M2 ;
int n , a[N] , b[N] ;
struct nn
{
	int lst , to ;
}E[2*N] ;
int head[2*N] , tot = 1 ;
inline void add( int x , int y )
{
	E[++tot] = (nn){ head[x] , y } ;
	head[x] = tot ;
}
int dfn[2*N] , low[2*N] , tim ;
bool bri[2*N] ;
vector<int> e[2*N] ;
void tarjan( int x , int inE )
{
	dfn[x] = low[x] = ++tim ;
	for(int i = head[x] ; i ; i = E[i].lst ) {
		int t = E[i].to ;
		if( !dfn[t] ) {
			tarjan( t , i ) ;
			low[x] = min( low[x] , low[t] ) ;
			if( low[t] > dfn[x] ) {
				bri[i] = bri[i^1] = 1 ;
			}
		}
		else if( i != (inE^1) ) {
			low[x] = min( low[x] , dfn[t] ) ;
		}
	}
}
int cnt , bol , bel[2*N] , A[2*N] , B[2*N] , SA[2*N] , SB[2*N] ;
void dfs( int x )
{
	bel[x] = cnt ;
	if( x <= M1 ) A[cnt] ++ ;
	else B[cnt] ++ ;
	for(int i = head[x] ; i ; i = E[i].lst ) {
		int t = E[i].to ;
		if( bri[i] ) {
			if( bel[t] ) {
				e[bel[t]].push_back( bel[x] ) ;
				e[bel[x]].push_back( bel[t] ) ;
			}
		}
		else if( !bel[t] ) dfs( t ) ;
	}
}
int PA[2*N] , PB[2*N] , ans1 , ans2 , ans3 , rt[2*N] ;
bool can[2*N] ; // 是否有非割边 
void get_size( int x , int fa )
{
	SA[x] = A[x] , SB[x] = B[x] ;
	if( A[x]+B[x] > 1 ) can[bol] = 1 ;
	for(int t : e[x] ) {
		if( t == fa ) continue ;
		get_size( t , x ) ;
		SA[x] += SA[t] ; SB[x] += SB[t] ;
	}
}
void ddfs( int x , int fa )
{
	for(int t : e[x] ) {
		if( t == fa ) continue ;
		ans2 = max( ans2 , min(PA[bol],PB[bol])-min(SA[t],SB[t])-min(PA[bol]-SA[t],PB[bol]-SB[t]) ) ; // 最多减少多少 
		ddfs( t , x ) ;
	}
}
int I , Mx1 , Mx2 ;
inline int V ( int a , int b , int c , int d ) // 合并后增加多少 / 拆开后损失多少 
{
	return min(a+c,b+d)-min(a,b)-min(c,d) ;
}
inline int V1( int a , int b )
{
	if( a > b ) return min(a-b,Mx2) ;
	return min(b-a,Mx1) ;
}
void Get( int x , int fa ) // 处理割边 
{
	for(int t : e[x] ) {
		if( t == fa ) continue ;
		ans3 = max( ans3 , -V(SA[t],SB[t],PA[I]-SA[t],PB[I]-SB[t])+V1(SA[t],SB[t]) ) ;
		ans3 = max( ans3 , -V(SA[t],SB[t],PA[I]-SA[t],PB[I]-SB[t])+V1(PA[I]-SA[t],PB[I]-SB[t]) ) ;
		Get( t , x ) ;
	}
}
void solve()
{
	cnt = 0 ; bol = 0 ;
	for(int i = 1 ; i <= M1+M2 ; i ++ ) {
		if( !dfn[i] ) {
			tarjan( i , 0 ) ;
		}
	}
	for(int i = 1 ; i <= M1+M2 ; i ++ ) {
		if( !bel[i] ) {
			cnt ++ ;
			dfs( i ) ;
		}
	}
	ans1 = ans2 = ans3 = 0 ;
	for(int i = 1 ; i <= cnt ; i ++ ) {
		if( !SA[i]&&!SB[i] ) {
			bol ++ ;
			rt[bol] = i ;
			get_size( i , 0 ) ;
			PA[bol] = SA[i] , PB[bol] = SB[i] ;
			ddfs( i , 0 ) ;
			ans1 += min(PA[bol],PB[bol]) ;
		}
	}
	ans2 = ans1-ans2 ;
	if( K == 0 ) {
		printf("%d\n" , ans1 ) ;
		return ;
	}
	if( K == 1 ) {
		printf("%d\n" , ans2 ) ;
		return ;
	}
	if( K == 2 ) {
		Mx1 = 0 , Mx2 = 0 ;
		if( M1 < n ) Mx1 = 1 ;
		if( M2 < n ) Mx2 = 1 ;
		for(int i = 1 ; i <= bol ; i ++ ) {
			Mx1 = max( Mx1 , PA[i]-PB[i] ) ;
			Mx2 = max( Mx2 , PB[i]-PA[i] ) ;
		}
		for(int i = 1 ; i <= bol ; i ++ ) {
			if( can[i] ) {
				if( PA[i] > PB[i] ) ans3 = max( ans3 , min(PA[i]-PB[i],Mx2) ) ;
				else ans3 = max( ans3 , min(PB[i]-PA[i],Mx1) ) ;
			}
			else {
				I = i ;
				Get( rt[i] , 0 ) ;
			}
		}
		printf("%d\n" , ans3+ans1 ) ;
		return ;
	}
}
int nam[N][2] ;	
void Clear()
{
	for(int i = 2 ; i <= tot ; i ++ ) bri[i] = 0 ;
	tot = 1 ;
	for(int i = 1 ; i <= M1+M2 ; i ++ ) head[i] = dfn[i] = bel[i] = 0 ;
	for(int i = 1 ; i <= n ; i ++ ) nam[i][0] = nam[i][1] = 0 ;
	tim = 0 ; 
	for(int i = 1 ; i <= cnt ; i ++ ) e[i].clear() , A[i] = B[i] = SA[i] = SB[i] = 0 ;
	for(int i = 1 ; i <= bol ; i ++ ) can[i] = 0 ; 
}

int main()
{
	scanf("%d%d" , &T , &K ) ;
	while( T -- ) {
		scanf("%d" , &n ) ;
		if( n == 1 ) {
			printf("1\n") ;
			for(int i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i] ) ;
			for(int i = 1 ; i <= n ; i ++ ) scanf("%d" , &b[i] ) ;
			continue ;
		}
		M1 = 0 , M2 = 0 ;
		for(int i = 1 ; i <= n ; i ++ ) {
			scanf("%d" , &a[i] ) ;
			if( !nam[a[i]][0] ) {
				nam[a[i]][0] = ++M1 ;
			}
			a[i] = nam[a[i]][0] ;
		}
		for(int i = 1 ; i <= n ; i ++ ) {
			scanf("%d" , &b[i] ) ;
			if( !nam[b[i]][1] ) {
				nam[b[i]][1] = ++M2 ;
			}
			b[i] = nam[b[i]][1] ;
			add( a[i] , b[i]+M1 ) , add( b[i]+M1 , a[i] ) ;
		}
		solve() ;
		Clear() ;
	}
	return 0 ;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1943454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端(1)HTML

1、标签 创建1.html文件&#xff0c;浏览器输入E:/frontheima/1.html&#xff0c;可以访问页面 页面展示 在VSCODE安装IDEA的快捷键&#xff0c;比如ctld复制一行、ctrlx剪切 <p id"p1" title"标题1">Hello,world!</p> <p id"p2"…

Java | Leetcode Java题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; class Solution {public int missingNumber(int[] nums) {int n nums.length;int total n * (n 1) / 2;int arrSum 0;for (int i 0; i < n; i) {arrSum nums[i];}return total - arrSum;} }

[排序]hoare快速排序

今天我们继续来讲排序部分&#xff0c;顾名思义&#xff0c;快速排序是一种特别高效的排序方法&#xff0c;在C语言中qsort函数&#xff0c;底层便是用快排所实现的&#xff0c;快排适用于各个项目中&#xff0c;特别的实用&#xff0c;下面我们就由浅入深的全面刨析快速排序。…

PHP接入consul,注册服务和发现服务【学习笔记】

PHP接入consul,注册服务和发现服务 consul安装 链接: consul安装 启动consul C:\Users\14684>consul agent -dev安装TP5 composer create-project topthink/think5.0.* tp5_pro --prefer-dist配置consul 创建tp5_pro/application/service/Consul.php <?php /*****…

环境变量配置文件中两种路径添加方式

环境变量配置文件中两种路径添加方式 文章目录 环境变量配置文件中两种路径添加方式代码示例区别和作用 代码示例 export HBASE_HOME/opt/software/hbase-2.3.5 export PATH$PATH:$HBASE_HOME/binexport SPARK_HOME/opt/software/spark-3.1.2 export PATH$SPARK_HOME/bin:$PAT…

【MySQL是怎样运行的 | 第一篇】Explain执行计划上

文章目录 1.查询优化-Explain语句详解上1.1前言1.2执行计划输出各列详解1.2.1 table1.2.2 id1.2.3 select_type1.2.4 partitions1.2.5 type1.2.6 possible_keys和key1.2.7 key_len1.2.8 ref1.2.9 rows 世纪晚霞 1.查询优化-Explain语句详解上 1.1前言 一条查询语句在经过 MyS…

在 CentOS 7 上安装 Docker 并安装和部署 .NET Core 3.1

1. 安装 Docker 步骤 1.1&#xff1a;更新包索引并安装依赖包 先安装yum的扩展&#xff0c;yum-utils提供了一些额外的工具&#xff0c;这些工具可以执行比基本yum命令更复杂的任务 sudo yum install -y yum-utils sudo yum update -y #更新系统上已安装的所有软件包到最新…

视频分帧【截取图片】(YOLO目标检测【生成数据集】)

高效率制作数据集【按这个流程走&#xff0c;速度很顶】 本次制作&#xff0c;1059张图片【马路上流动车辆】 几乎就是全自动了&#xff0c;只要视频拍得好&#xff0c;YOLO辅助制作数据集就效率极高 视频中的图片抽取&#xff1a; 【由于视频内存过大&#xff0c;遇到报错执行…

2024导游资格考试,这些材料提前准备✅

2024年导游考试报名本月开始&#xff01; &#x1f499;大家提前准备好报名材料 1、个人近期白底1寸证件照。 2、身份证照片 3、学历照片 4、健康证明或健康承诺书 5、其他需要上传的材料 &#x1f499;照片文件不通过原因汇总&#xff0c;记得避开这些坑&#xff01; &#x1…

网络驱动移植(RTL8189)

1、把驱动放到内核文件夹中&#xff08;linux/drivers/net/wireless&#xff09;&#xff0c;对应的驱动可以在网上下载 2、修改该目录下的Kconfig和Makefile文件 3、配置内核&#xff08;make menuconfig&#xff09; 配置支持IEEE 802.11&#xff0c;选中8189模块&#xff0…

程序员 被辞退后如何赚钱

为啥现在大厂大量裁员&#xff1f;35以上的程序员为啥不被认可&#xff0c;很难找工作&#xff1f; 技术更新换代迅速&#xff1a; 技术领域发展极快&#xff0c;新的编程语言、框架和技术不断涌现。如果大龄程序员未能及时学习新技术和跟上行业变化&#xff0c;可能会被新一代…

SAP第二季度财报和进一步裁员计划

7月22日公布了截至 2024 年 6 月 30 日的第二季度财务报告。以下位总体指标 当前云计算在手订单达 148 亿欧元&#xff0c;按名义货币和固定汇率计算均增长 28%云收入增长 25%&#xff0c;其中云 ERP 套件收入增长 33%&#xff0c;均按名义货币和固定汇率计算总收入增长 10%&a…

【数据结构初阶】复杂度

目录 一、时间复杂度 1、时间复杂度的概念 2、大O的渐进表示法 3、常见的时间复杂度计算举例 二、空间复杂度 1、空间复杂度的概念 2、常见的空间复杂度计算举例 三、常见复杂度对比 正文开始—— 前言 一个算法&#xff0c;并非越简洁越好&#xff0c;那该如何衡量一个算法…

Mamba-yolo|结合Mamba注意力机制的视觉检测

一、本文介绍 PDF地址&#xff1a;https://arxiv.org/pdf/2405.16605v1 代码地址&#xff1a;GitHub - LeapLabTHU/MLLA: Official repository of MLLA Demystify Mamba in Vision: A Linear AttentionPerspective一文中引入Baseline Mamba&#xff0c;指明Mamba在处理各种高…

零基础入门:创建一个简单的Python爬虫管理系统

摘要&#xff1a; 本文将手把手教你&#xff0c;从零开始构建一个简易的Python爬虫管理系统&#xff0c;无需编程基础&#xff0c;轻松掌握数据抓取技巧。通过实战演练&#xff0c;你将学会设置项目、编写基本爬虫代码、管理爬取任务与数据&#xff0c;为个人研究或企业需求奠…

回溯题目的套路总结

前言 昨天写完了LeeCode的7&#xff0c;8道回溯算法的题目&#xff0c;写一下总结&#xff0c;这类题目的共同特点就是暴力搜索问题&#xff0c;排列组合或者递归&#xff0c;枚举出所有可能的答案&#xff0c;思路很简单&#xff0c;实现起来的套路也很通用&#xff0c;一…

poi库简单使用(java如何实现动态替换模板Word内容)

目录 Blue留言&#xff1a; Blue的推荐&#xff1a; 什么是poi库&#xff1f; 实现动态替换 第一步&#xff1a;依赖 第二步&#xff1a;实现word模板中替换文字 模板word&#xff1a; 通过以下代码&#xff1a;&#xff08;自己建一个类&#xff0c;随意取名&#xf…

SpringBoot框架学习笔记(五):静态资源访问、Rest风格请求处理、配置视图解析器、接收参数的相关注解详解

1 WEB开发-静态资源访问 1.1 基本介绍 &#xff08;1&#xff09;只要静态资源放在类路径的以下目录&#xff1a;/static、/public、/resources、/META-INF/resources 可以被直接访问。maven项目的类路径即为main/resources目录--对应SpringBoot源码为WebProperties.java类 …

nginx如何开启优先访问压缩文件

nginx输出gzip有很多条件&#xff1a; 开启了gzip&#xff1a;gzip on;gzip_types定义了content-type&#xff0c;需要注意的是text/html是强制性的&#xff0c;不需要也不能再添加这个响应输出的content-type在gzip_types里输出的content-length大于等于nginx配置的gzip_min_…

【TypeScript 一点点教程】

文章目录 一、开发环境搭建二、基本类型2.1 类型声明2.2 基本类型 三、编译3.1 tsc命令3.2 tsconfig.json3.2.1 基本配置项includeexcludeextendsfiles 3.2.2 compilerOptions编译器的配置项 四、面向对象4.1 类4.2 继承4.3 抽象类4.4 接口 一、开发环境搭建 下载Node.js《Nod…