【过题记录】7.31(树形dp,根号分治)

news2024/9/22 10:00:04
先补一下昨天没来得及写的题目

延时操控


分析:

由于是延时操控
所以敌人的前面几步跟我们走的是一样的
所不一样的是我们比敌人多走了k步
所以我们可以先让我们和敌人同步行走,最后让我们随机游走k步即可。
由于这里n和m的范围都很小,所以我们有一个初步的dp设想:
f [ i ] [ x ] [ y ] [ d m g ] [ x x ] [ y y ] f[i][x][y][dmg][xx][yy] f[i][x][y][dmg][xx][yy]
表示经过了i轮,我们走到了 ( x , y ) (x,y) (x,y),敌人走到了 ( x x , y y ) (xx,yy) (xx,yy),已经扣了敌人dmg滴血的方案数。
但是这样的复杂度显然会超。
我们尝试优化状态
其实,由于我们和敌人这时是同步走的,所以如果敌人不扣血,我们和敌人之间的位置差是一定的
就是初始的位置差。
这个时候我们可以直接确定敌人的位置。
但是如果敌人扣血了,那么位置偏差就会有改变。
最多会改变多少呢?
扣了几滴血,最多就会改变多少。
所以我们可以优化上述的dp状态为:
f [ i ] [ x ] [ y ] [ d m g [ d e l x ] [ d e l y ] f[i][x][y][dmg[delx][dely] f[i][x][y][dmg[delx][dely]
表示敌人的位置跟初始时候想比,x偏差了delx,y偏差了dely时的方案数。
这样就成功优化了状态。
同时当前的状态只能通过前一轮的状态转移过来,所以第一维我们又可以通过滚动数组去优化。


#include<iostream>
using namespace std;

#define int long long

const int N = 80,K = 5;
const int P = 1000000007;
int f[4][N][N][8][20][20],g[4][N][N];
int n,m,de,hp;
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
bool vi[N][N];

#define gc getchar()

void Clear(int ll){
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++)
	    for (int k = 0; k <= hp; k++)
	      for (int delx = -k; delx <= k; delx++){
	      	  int Max = k-abs(delx);
	      	  for (int dely = -Max; dely <= Max; dely++)
	      	    f[ll][i][j][k][delx+K][dely+K] = 0;
		  }
//	        for (int dely = 0; dely < 11; dely++)
//	          f[ll][i][j][k][delx][dely] = 0;
}

bool Check(int x,int y){
	if (x < 1 || x > n || y < 1 || y > n) return 0;
	if (vi[x][y] == 0) return 0;
	return 1;
}

void Add(int &x,int y){
	if (x+y < P) x = x+y; else x = x+y-P;
}

void Work(){
	cin>>n>>m>>de>>hp;
	Clear(0); Clear(1);
	for (int l = 0; l < 2; l++)
	  for (int i = 1; i <= n; i++)
	    for (int j = 1; j <= n; j++)
	      g[l][i][j] = 0;
	
	for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) vi[i][j] = 1;
	
	int stx,sty,edx,edy;
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++){
	  	  char ch = gc;
	  	  while (ch!='#' && ch!='.' && ch!='P' && ch!='E') ch = gc;
	  	  if (ch == '.') continue;
	  	  if (ch == '#') vi[i][j] = 0;
	  	  if (ch == 'P') stx = i , sty = j;
	  	  if (ch == 'E') edx = i , edy = j;
	  }
	edx-=stx; edy-=sty;
	int O = 0;
	f[0][stx][sty][0][K][K] = 1;
	m-=de;
	for (int l = 1; l <= m; l++){
		Clear(O^1);
		for (int i = 1; i <= n; i++){
		    for (int j = 1; j <= n; j++)
		      for (int k = 0; k < hp; k++)
		        for (int delx = -k; delx <= k; delx++){
		            int Max = k-abs(delx);
		            for (int dely = -Max; dely <= Max; dely++){
		          	    int now = f[O][i][j][k][delx+K][dely+K]; if (now == 0) continue;
		          	    for (int o = 0; o < 4; o++){
		          	        int xx = i+dx[o] , yy = j+dy[o];
						    if (Check(xx,yy) == 0) continue;
						    if (Check(xx+edx+delx,yy+edy+dely)) Add(f[O^1][xx][yy][k][delx+K][dely+K],now);
						    else if (k == hp-1) Add(g[0][xx][yy],now);
						    else Add(f[O^1][xx][yy][k+1][delx-dx[o]+K][dely-dy[o]+K],now);
					    }
				    }
			    }
		}
		O^=1;
	}
    O = 0;
	for (int l = 0; l < de; l++){
		for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) g[O^1][i][j] = 0;
		for (int i = 1; i <= n; i++)
		  for (int j = 1; j <= n; j++){
		  	  int now = g[O][i][j]; if (now == 0) continue;
		  	  for (int o = 0; o < 4; o++){
		  	      int x = i+dx[o] , y = j+dy[o];
				  if (Check(x,y) == 0) continue;
				  Add(g[O^1][x][y],now);	
			  }
		  }
		  O^=1;
	}
	int ans = 0;
	int l = O;
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++) Add(ans,g[l][i][j]);
	cout<<ans<<endl;
	return;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int t; cin>>t; while (t--) Work();
	return 0;
}

小凸玩密室

在这里插入图片描述


分析:

这个题给了几个比较强的限制条件
完全二叉树,开了一个灯之后必须把当前子树所有灯都打开才能开子树外的灯。
这就决定了,我们如果想将子树x的灯全都打开,要么就是先开左子树的灯再开右子树的灯,那么就是反过来。
所以当前子树的答案中一定有左右两颗子树的贡献
然后还要再加上一项跨子树的贡献。这个子树是怎么跨的呢?
一定是从一棵树的叶子节点跨越到另一边的根节点中。
也就是说如果我们想计算当前的答案,我们需要知道他想从哪一个叶子节点跨越过来,这就形成了我们的dp状态:
f [ u ] [ x ] f[u][x] f[u][x]表示以u为根的子树,当前再叶子结点x结束的最小贡献。
如果我们想先访问左子树
那么我们就需要枚举左子树的结束节点x以及右子树的结束节点y,按照如下方式转移:
f [ u ] [ y ] = m i n { D ( u , l u ) ∗ A [ l u ] + f [ l u ] [ x ] + D ( x , r u ) ∗ A [ r u ] + f [ r u ] [ y ] } f[u][y]=min\{D(u,lu)*A[lu]+f[lu][x]+D(x,ru)*A[ru]+f[ru][y]\} f[u][y]=min{D(u,lu)A[lu]+f[lu][x]+D(x,ru)A[ru]+f[ru][y]}
这样枚举x,y转移的复杂度就是 O ( n 3 ) O(n^3) O(n3)
还是会超时。
这个时候如果我们分解一下上式,我们发现,如果想要最小化 f [ u ] [ y ] f[u][y] f[u][y]
其实就是要最小化 f [ l u ] [ x ] + D ( x , u ) ∗ A [ r u ] f[lu][x]+D(x,u)*A[ru] f[lu][x]+D(x,u)A[ru]因为其他的几项可以当做常数处理
这个意思是,对于每一个y,他转移过来的对应的x都是一样的,就是那个最小值对应的minx
这个的最小值我们可以 O ( 叶子数 ) O(叶子数) O(叶子数)预处理
而转移同样也是 O ( 叶子数 ) O(叶子数) O(叶子数)
这颗二叉树一共有 O ( l o g n ) O(logn) O(logn)层,每一层的复杂度都是叶子个数
所以总的复杂度就是 O ( n l o g n ) O(nlogn) O(nlogn)
还有一个注意点,就是这个题不一定是从1开始的
所以还需要跑一个换根dp
确实有点麻烦
问题不大


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

#define int long long

const int N = 2e6+100,inf = 1e19;
int n;
int a[N],b[N];
vector < int > dp[N],Dp[N],d[N];
#define pb push_back
int de[N];

void Dfs(int x){
	de[x] = de[x/2]+b[x];
	if (x*2 > n){
		for (int i = x; i >= 1; i/=2)
		  dp[i].pb(0), Dp[i].pb(0), d[i].pb(de[x]-de[i]);
		return;
	}
	Dfs(x*2);
	int t = dp[x*2].size();
	if (x*2+1 > n){
		dp[x][0] = b[2*x]*a[2*x];
		Dp[x][0] = dp[x][0];
		return;
	}
	Dfs(x*2+1);
	int ans1 = inf , ans2 = inf , Ans1 = inf , Ans2 = inf;
	for (int i = 0; i < dp[x].size(); i++){
		if (i < t){
			ans1 = min(ans1,dp[x*2][i]+b[x*2]*a[x*2]+(d[x][i]+b[x*2+1])*a[x*2+1]);
			Ans1 = min(Ans1,Dp[x*2][i]+d[x][i]*a[x]+b[2*x+1]*a[2*x+1]);
		}
		else{
			ans2 = min(ans2,dp[x*2+1][i-t]+b[2*x+1]*a[2*x+1]+(d[x][i]+b[2*x])*a[2*x]);
			Ans2 = min(Ans2,Dp[x*2+1][i-t]+d[x][i]*a[x]+b[2*x]*a[2*x]);
		}
	}
	for (int i = 0; i < dp[x].size(); i++){
		if (i < t){
			dp[x][i] = ans2+dp[2*x][i];
			Dp[x][i] = min(dp[x][i],Ans2+dp[2*x][i]);//换根 
		}
		else{
			dp[x][i] = ans1+dp[2*x+1][i-t];
			Dp[x][i] = min(dp[x][i],Ans1+dp[2*x+1][i-t]);//换根 
		}
	}
	return ;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(false); 
	cin>>n;
	for (int i = 1; i <= n; i++) cin>>a[i];
	for (int i = 2; i <= n; i++) cin>>b[i];
	Dfs(1);
	int Min = inf;
	for (int i = 0; i < Dp[1].size(); i++)
	  Min = min(Min,Dp[1][i]);
	cout<<Min<<endl;
	return 0;
}

哈希冲突

在这里插入图片描述


分析:

这是一道根号分治板题
我们先考虑暴力做法:
枚举起点x,不断加p跳跃
复杂度 O ( n ∗ n / p ) O(n*n/p) O(nn/p)
而后在考虑一个dp做法:
f [ i ] [ j ] f[i][j] f[i][j]表示起点为i,模数为j时的答案
想要求出这个dp的复杂度是
O ( n p ) O(np) O(np)
我们发现,一边的复杂度是 n 2 / p n^2/p n2/p,一边是 n p np np
怎么样能让两个的复杂度趋于稳定呢?
那就是让 n 2 / p = n p n^2/p=np n2/p=np
p= ( n ) \sqrt(n) ( n)
没错,这个时候p就是阈值,大于这个阈值,我们采用暴力
小于这个阈值,我们采用dp O ( 1 ) O(1) O(1)输出
总的复杂度 O ( n n ) O(n\sqrt n) O(nn )


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

const int N = 2e5+100;
int n,m;
int a[N];
int s[5000][5000];
typedef pair < int , int > pii;
vector < pii > ch;
#define fi first
#define se second

int Calc(int st,int p){
	int sum = 0;
	for (int i = st; i <= n; i+=p)
	  sum+=a[i];
	return sum;
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for (int i = 1; i <= n; i++) cin>>a[i];
	int di = int(sqrt(n));
	for (int p = 1; p <= di; p++)
	  for (int i = 1; i <= n; i++)
	    s[i%p][p]+=a[i];
	for (int i = 1; i <= m; i++){
		string s1; int x,y; 
		cin>>s1>>x>>y; 
		if (s1 == "A"){
			if (x <= di) cout<<s[y%x][x]<<endl;
			else cout<<Calc(y,x)<<endl;
		}
		else{
			for (int p = 1; p <= di; p++) s[x%p][p]+=y-a[x];
			a[x] = y;
		}
	}
	return 0;
}

Remainder Problem

在这里插入图片描述


分析:

根上一题几乎一样
不同的是=变成+=


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

//#define int long long

const int N = 5e5+10;
int q;
int s[5000][5000];
int a[N];

int Calc(int st,int p){
	int sum = 0;
	for (int i = st; i <= N-10; i+=p)
	  sum+=a[i];
	return sum;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int di = (sqrt(N-100000));
	cin>>q;
	while (q--){
		int op,x,y;
		cin>>op>>x>>y;
		if (op == 1){
			a[x]+=y;
			for (int i = 1; i <= di; i++) s[x%i][i]+=y;
		}
		else{
			if (x <= di) cout<<s[y][x]<<endl;
			else cout<<Calc(y,x)<<endl;
		}
	}
	return 0;
}

Array Queries

在这里插入图片描述


其实思路大同小异
f [ i ] [ j ] f[i][j] f[i][j]表示从位置i开始,步长为j时要跳的步数是多少。
f [ i ] [ j ] = f [ i + a [ i ] + j ] [ j ] + 1 f[i][j]=f[i+a[i]+j][j]+1 f[i][j]=f[i+a[i]+j][j]+1


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

const int N = 1e5+10,M = 318;
int f[N][M];
int n;
int a[N];

int Calc(int st,int p){
	int cnt = 0;
	while (st <= n) st = st+a[st]+p,cnt++;
	return cnt; 
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin>>n;
	for (int i = 1; i <= n; i++) cin>>a[i];
	for (int p = 1; p < M; p++)
	  for (int i = n; i >= 1; i--)
	    if (i+a[i]+p > n) f[i][p] = 1;
	    else f[i][p] = f[i+a[i]+p][p]+1;
	    
	int q; cin>>q;
	while (q--){
		int p,k; cin>>p>>k;
		if (p > n){
			cout<<0<<endl; continue;
		}
		if (k < M) cout<<f[p][k]<<endl;
		else cout<<Calc(p,k)<<endl;
	}
	return 0;
}

Sum of Progression

在这里插入图片描述


维护两个前缀和数组
f [ i ] [ j ] f[i][j] f[i][j]表示从1以步长j跳到i时的答案, s [ i ] [ j ] s[i][j] s[i][j]则表示单纯的前缀和数组
计算答案是多余的答案利用前缀和s数组减去即可
有一点需要注意的是因为这个题是多组数据
所以对于每一个n,我们都要单独计算阈值
不然会超时。
还有,最好小的那一维放前面,这样可以减少一些寻址的复杂度


#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define ll long long
const int N = 1e5+10 , M = 318;
int n;
int a[N];
ll f[M][N];
ll s[M][N];

ll Calc(int now,int p,int k){
	ll sum = 0;
	for (int i = 0; i < k; i++){
		sum+=1ll*a[now]*(i+1); now+=p;
	}
	return sum;
}
int q;
void Work(){
	cin>>n>>q;
	for (int i = 1; i <= n; i++) cin>>a[i];
	int div = sqrt(n);
	for (int p = 1; p <= div; p++)
	  for (int st = 1; st <= p; st++){
	  	  f[p][st] = a[st]; s[p][st] = a[st];
	      for (int i = st+p,j=2; i <= n; i+=p,j++)
	        f[p][i] = (f[p][i-p]+1ll*j*a[i]),s[p][i] = s[p][i-p]+1ll*a[i];
	}
	while (q--){
		int now,p,k;
		cin>>now>>p>>k;
		int st = now%p;
		if (st == 0) st = p;
		int ed = now+(k-1)*p;
		int C = (now-st)/p;
		int la = max(0,now-p);
		if (p <= div){
			ll ans = f[p][ed]-f[p][la];
			ans = ans-(s[p][ed]-s[p][la])*C;
			cout<<ans<<' ';
		}
		else cout<<Calc(now,p,k)<<' ';
	}
	cout<<endl;
	for (int p = 1; p < M; p++)
	  for (int i = 1; i <= n; i++) f[p][i] = 0 , s[p][i] = 0;
	return;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int t; cin>>t; while (t--) Work();
	return 0;
}
/*
5
3 1
-100000000 -100000000 -100000000
1 1 3
*/

通知

根号分治


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

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

相关文章

力扣 位运算

位运算基础的异或运算&#xff0c;线性时间复杂度和常数空间复杂度。 题目 class Solution {public int singleNumber(int[] nums) {int ans 0;for (int i: nums) {ans ^ i;}return ans;} }

Linux下用户组练习

目录 建立用户组 shengcan&#xff0c;其id 为 2000 建立用户组 caiwu&#xff0c;其id为 2001 建立用户组 jishu&#xff0c;其id 为 2002 建立用户lee&#xff0c;指定其主组id为shengchan&#xff0c;附加组为jishu和 caiwu&#xff0c;确保 lee 用户的uid 和 gid 保持一…

C++客户端Qt开发——界面优化(绘图)

2.绘图 Qt提供了画图相关的APL&#xff0c;可以允许我们在窗口上绘制任意的图形形状&#xff0c;来完成更复杂的界面设计 所谓的"控件"&#xff0c;本质上也是通过画图的方式画上去的 画图AP|和控件之间的关系&#xff0c;可以类比成机器指令和高级语言之间的关系…

大模型“挣钱”新方法!用GPT-4优化众筹文稿,提高筹款成功率11.9%!

怎么才能在大模型时代&#xff0c;更好地通过大模型&#xff08;LLM&#xff09;来挣钱&#xff1f;写软文拿打赏&#xff0c;画海报给甲方&#xff0c;或者制作视频来打造个人IP&#xff1f;不够&#xff0c;还想要更直接一点的方式&#xff1f;那有没有一种可能&#xff0c;直…

密码学基础-为什么使用真随机数(True Random Number Generators)

密码学基础-为什么使用真随机数&#xff08;True Random Number Generators&#xff09; 概述 随机的意义很重要&#xff0c;就像你的银行密码如果是亲朋好友的生日&#xff0c;结婚纪念日&#xff08;可预测的&#xff09;&#xff0c;那么就容易被人测试出来&#xff1b;而…

Centos 7配置问题

在VMWare12上面安装Centos 7 Linux虚拟机&#xff0c;在切换到命令界面时&#xff0c;需要登录用户名和密码&#xff0c;但发现输入用户后有字符显示&#xff0c;但是密码没有。 经过一系列查看后&#xff0c;发现这个是Linux的一种机制&#xff0c;即当你输入密码时不显示&…

Python批量移除Word文档水印

Word文档被广泛用于各种正式与非正式的沟通场合。有时候这些文档中可能包含着不再需要的水印&#xff0c;比如早期的草稿标记、保密声明或是仅供预览的信息等。这些水印的存在可能会干扰文档的阅读体验&#xff0c;甚至在某些情况下导致信息传达的不准确或产生误解。移除Word文…

QT:多版本同时使用(5.15.2在线安装教程)

前言 根据不同项目的需要有时候不得不安装多个版本的QT&#xff0c;新版本的QT都需要在线安装&#xff0c;以下为QT5.15.2的在线安装办法&#xff08;5.15.2为LTS版本相对更稳定&#xff09;&#xff0c;老版本可参考之前的离线安装&#xff0c; 版本选择 比如 5.15.2 是完整的…

昇思25天学习打卡营第XX天|Diffusion扩散模型

扩散模型自DDPM论文提出后&#xff0c;在图像生成领域取得了显著进展&#xff0c;特别是在文本条件图像生成方面。重要发展包括改进的去噪模型&#xff0c;级联扩散模型以提高图像分辨率&#xff0c;以及无需分类器的扩散模型指导。DALL-E 2和ImageGen等模型展示了结合语言模型…

7.29 Day11 LVM逻辑卷管理

LVM逻辑卷管理&#xff1a; 优点&#xff1a;将多个磁盘进行统一管理&#xff0c;易于扩容 缺点&#xff1a;不支持容错&#xff08;任意一个磁盘坏了&#xff0c;整个磁盘都会坏&#xff09; 实现步骤&#xff1a; 对磁盘进行分区--改为8e--PV&#xff08;物理卷&#xff0…

pythonGame-实现羊了个羊简易字母版

通过python简单复现羊了个羊游戏。 使用到的库函数&#xff1a; import pygame import random 游戏源码&#xff1a; import pygame import random# 初始化pygame pygame.init()# 设置窗口大小 WIDTH 800 HEIGHT 600 screen pygame.display.set_mode((WIDTH, HEIGHT)) p…

基于N32L406MB EasyFlash参数(key-value)记录库移植

EasyFlash 感谢作者的分享https://github.com/armink/EasyFlash EasyFlash是一款开源的轻量级嵌入式Flash存储器库&#xff0c;方便开发者更加轻松的实现基于Flash存储器的常见应用开发 三大实用功能 ENV快速保存产品参数(key-value)&#xff0c;支持 写平衡&#xff08;磨…

文心智能体零代码开发实践,创建一个智能体:从理论到实践AI技术落地

文心智能体引领零代码智能体开发新风尚&#xff0c;诚邀您一同探索这前沿科技的魅力&#xff01;以下为实践创建一个叫”从理论到实践AI技术落地“智能体的步骤。 首先登录官网&#xff1a;文心智能体平台AgentBuilder | 想象即现实 登录后点击&#xff1a;创建智能体 输入“…

《660》+《880》强化带刷计划‼️45天吃透所有核心知识点

如果把660吃透再去做880&#xff0c;肯定会轻松一些&#xff01; 因为660题对于基础的考查很深入&#xff0c;每一道题都有难度&#xff0c;都需要认真思考才能做出来&#xff0c;所以&#xff0c;660建议在基础结束之后再开始做&#xff0c;因为基础阶段本身对基础知识的理解…

240731-一图解释LM-Studio如何设置模型的国内下载

感谢微信公众号作者数翼分享的文章 — 本地 LLM 可视化工具 LM Studio 突破国内网络限制使用 A. 图文指南 B. 具体步骤 Step 1. 安装软件并通过VSCode等编辑打开软件所在目录 官网下载并安装。随后找到软件的安装路径&#xff0c;并通过VSCode打开。 Step 2. 全局替换 被替…

2024年8月1日 十二生肖 今日运势

小运播报&#xff1a;2024年8月1日&#xff0c;星期四&#xff0c;农历六月廿七 &#xff08;甲辰年辛未月丁酉日&#xff09;&#xff0c;法定工作日。今天建军节&#xff0c;祝保家卫国、英勇无畏的解放军战士们节日快乐&#xff01; 红榜生肖&#xff1a;龙、牛、猪 需要注…

JavaSE基础 (认识String类)

一&#xff0c;什么是String类 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提 供的字符串系列函数完成大部分操作&#xff0c;但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想&…

vue中scoped详解以及样式穿透>>>、/deep/、::v-deep

1、scoped scoped属性用于限制样式仅应用于当前组件。当一个style标签拥有scoped属性时&#xff0c;它的CSS样式就只能作用于当前的组件&#xff0c;通过该属性&#xff0c;可以使得组件之间的样式不互相污染。 原理&#xff1a;当样式中加了scoped属性时候&#xff0c;编译的…

解决 Python 中 AttributeError: module ‘typing‘ has no attribute ‘_ClassVar‘

启动 Flask 的时候遇到&#xff1a; AttributeError: module typing has no attribute _ClassVar 卸载 dataclasses pip uninstall dataclasses 启动 Flask 正常

jenkins pipeline 发布 jar并运行

废话不多说&#xff0c;上教程 一&#xff0c;配置publish ssh 二&#xff0c;配置 ssh server 记住Name 三 设置发布选项 1 设置模块多选&#xff08;请安装多选插件&#xff1a;Active Choices Plug-in&#xff09; ​ ​ 四 编写pipeline 说明&#xff1a; 1 module…