Comet OJ - 模拟赛 #1

本文解析了NOIP2018竞赛中的六道题目,包括双指针算法、最小生成树、线段树、矩形交集、优化DP及高维前缀和等高级算法的应用。每道题目的解析深入浅出,旨在帮助读者理解并掌握算法背后的逻辑。

正题

      1个半小时就可以AK的题目

      A

      发现一个点只会被吸一次,那么就是找对应区间,双指针即可,求答案的时候注意一下两边有0的情况。

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

const int N=100010;
int T,n;
int a[N],b[N];

void read(int&x){
	char ch=getchar();x=0;
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
}

int main(){
	read(T);
	while(T--){
		read(n);
		long long t1=0,t2=0;
		for(int i=1;i<=n;i++) read(a[i]),t1+=a[i];
		for(int i=1;i<=n;i++) read(b[i]),t2+=b[i];
		if(t1!=t2){printf("-1\n");continue;}
		int pos1=1,pos2=1,tot=0,ans=0;
		bool tf=true;
		while(pos1<=n && pos2<=n){
			tot=0;
			bool we=false;
			while(tot<b[pos2]){
				tot+=a[pos1];
				if(pos1!=pos2 && a[pos1] && !we) we=true,ans++;pos1++;
				if(tot==b[pos2]) break;
				else if(tot>b[pos2]) {tf=false;break;}
			}
			if(!tf) break;
			pos2++;
		}
		if(!tf) printf("-1\n");
		else printf("%d\n",ans);
	}
}

      B

      最小生成树即可,容易证明一条新加进来的边若联通两个已经联通的点,那么肯定没有前面所有加起来优。

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

const int N=300010;
struct edge{
	int y,next,c;
}s[N<<1];
int n,m,q;
int first[N],len=0;
int fa[N],dep[N],f[N][20];
long long dis[N];
const long long mod=998244353;

int findpa(int x){return fa[x]!=x?fa[x]=findpa(fa[x]):x;}

void ins(int x,int y,int c){
	s[++len]=(edge){y,first[x],c};first[x]=len;
	s[++len]=(edge){x,first[y],c};first[y]=len;
}

void dfs(int x,int fa){
	for(int i=first[x];i!=0;i=s[i].next) if(s[i].y!=fa){
		int y=s[i].y;
		dep[y]=dep[x]+1;f[y][0]=x;dis[y]=dis[x]+s[i].c;
		for(int k=1;k<=19;k++) f[y][k]=f[f[y][k-1]][k-1];
		dfs(y,x);
	}
}

int lca(int x,int y){
	if(dep[x]>dep[y]) swap(x,y);
	for(int k=19;k>=0;k--) if(dep[f[y][k]]>=dep[x]) y=f[y][k];
	if(x==y) return x;
	for(int k=19;k>=0;k--) if(f[x][k]!=f[y][k]) x=f[x][k],y=f[y][k];
	return f[x][0];
}

int main(){
	scanf("%d %d",&n,&m);
	int x,y,c=1;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++){
		scanf("%d %d",&x,&y),c=c*2%mod;
		int fx=findpa(x),fy=findpa(y);
		if(fx!=fy) ins(x,y,c),fa[fx]=fy;
	}
	dep[1]=1,dfs(1,0);
	scanf("%d",&q);
	while(q--){
		scanf("%d %d",&x,&y);
		printf("%lld\n",(dis[x]+dis[y]-2*dis[lca(x,y)])%mod);
	}
}

      C

      把ai从大到小排序之后,把式子写出来:

      \frac{\sum_{i=1}^n 2^{n-i}\sum_{j=0}^{i-1}C_{i-1}^j(\frac{1}{2})^{j+1}*a_i}{2^{n}} \\=\frac{\sum_{i=1}^n 2^{n-i}(1+\frac{1}{2})^{i-1}*a_i}{2^{n+1}} \\=\sum_{i=1}^{n}3^{i-1}2^{-2i}*a_i \\=\frac{\sum_{i=1}^n(\frac{3}{4})^ia_i}{3}

      那么直接维护一个线段树或者树状数组就可以了。

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

const int N=100010;
int n,m,rt,num;
int a[N];
int lazy[10000010],sum[10000010],t[10000010],ls[10000010],rs[10000010];
int ci[N];
const long long mod=998244353,data=249561089,fuck=332748119;

void pushdown(int now){
	if(lazy[now]!=1){
		if(ls[now]) lazy[ls[now]]=1ll*lazy[ls[now]]*lazy[now]%mod,sum[ls[now]]=1ll*sum[ls[now]]*lazy[now]%mod;
		if(rs[now]) lazy[rs[now]]=1ll*lazy[rs[now]]*lazy[now]%mod,sum[rs[now]]=1ll*sum[rs[now]]*lazy[now]%mod;
		lazy[now]=1;
	}
}

void times(int now,int x,int y,int c,int l,int r){
	if(!now) return;
	if(x==l && y==r){
		lazy[now]=1ll*lazy[now]*c%mod;
		sum[now]=1ll*sum[now]*c%mod;
		return ;
	}
	pushdown(now);
	int mid=(l+r)/2;
	if(y<=mid) times(ls[now],x,y,c,l,mid);
	else if(mid<x) times(rs[now],x,y,c,mid+1,r);
	else times(ls[now],x,mid,c,l,mid),times(rs[now],mid+1,y,c,mid+1,r);
	sum[now]=sum[ls[now]]+sum[rs[now]];
	sum[now]>=mod?sum[now]-=mod:0;
}

void add(int&now,int x,int c,int op,int l,int r){
	if(!now) now=++num,lazy[now]=1;
	sum[now]+=c;sum[now]>=mod?sum[now]-=mod:0;t[now]+=op;
	if(l==r) return ;
	pushdown(now);
	int mid=(l+r)/2;
	if(x<=mid) add(ls[now],x,c,op,l,mid);
	else add(rs[now],x,c,op,mid+1,r);
}

int get_tot(int now,int x,int y,int l,int r){
	if(!now) return 0;
	if(x==l && y==r) return t[now];
	pushdown(now);
	int mid=(l+r)/2;
	if(y<=mid) return get_tot(ls[now],x,y,l,mid);
	else if(mid<x) return get_tot(rs[now],x,y,mid+1,r);
	else return get_tot(ls[now],x,mid,l,mid)+get_tot(rs[now],mid+1,y,mid+1,r);
}

int get_sum(int now,int x,int y,int l,int r){
	if(!now) return 0;
	if(x==l && y==r) return sum[now];
	pushdown(now);
	int mid=(l+r)/2;
	if(y<=mid) return get_sum(ls[now],x,y,l,mid);
	else if(mid<x) return get_sum(rs[now],x,y,mid+1,r);
	else return (get_sum(ls[now],x,mid,l,mid)+get_sum(rs[now],mid+1,y,mid+1,r))%mod;
}

int main(){
	scanf("%d",&n);
	ci[0]=1;for(int i=1;i<=n;i++) ci[i]=1ll*ci[i-1]*data%mod;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		times(rt,0,a[i],data,0,998244352);
		add(rt,a[i],1ll*a[i]*ci[get_tot(rt,a[i]+1,998244352,0,998244352)+1]%mod,1,0,998244352);
	}
	int x,y;
	scanf("%d",&m);
	printf("%lld\n",1ll*sum[1]*332748118%mod);
	for(int i=1;i<=m;i++){
		scanf("%d %d",&x,&y);
		if(y<a[x]){
			if(y+1<=a[x]-1) times(rt,y+1,a[x]-1,fuck,0,998244352);
			add(rt,a[x],mod-1ll*a[x]*ci[get_tot(rt,a[x],998244352,0,998244352)]%mod,-1,0,998244352);
			add(rt,y,1ll*y*ci[get_tot(rt,y+1,998244352,0,998244352)+1]%mod,1,0,998244352);
		}
		else if(a[x]<y){
			if(a[x]+1<=y-1) times(rt,a[x]+1,y-1,data,0,998244352);
			add(rt,a[x],mod-1ll*a[x]*ci[get_tot(rt,a[x]+1,998244352,0,998244352)+1]%mod,-1,0,998244352);
			add(rt,y,1ll*y*ci[get_tot(rt,y,998244352,0,998244352)+1]%mod,1,0,998244352);
		}
		a[x]=y;
		printf("%lld\n",1ll*sum[1]*332748118%mod);
	}
}

      D

      n-1个的矩形交,发现n个矩形交会被算n次,减掉就可以了,其他用前缀后缀来维护。

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

const int N=200010;
int n,r,c;
long long tot=0,t=0;
int xx1[N],xx2[N],yy1[N],yy2[N];
int px1[N],px2[N],py1[N],py2[N];
int lx1[N],lx2[N],ly1[N],ly2[N];

int main(){
	scanf("%d %d %d",&n,&r,&c);
	for(int i=1;i<=n;i++) scanf("%d %d %d %d",&xx1[i],&yy1[i],&xx2[i],&yy2[i]);
	px2[0]=py2[0]=1e9;lx2[n+1]=ly2[n+1]=1e9;
	for(int i=1;i<=n;i++) px1[i]=max(px1[i-1],xx1[i]),py1[i]=max(py1[i-1],yy1[i]),px2[i]=min(px2[i-1],xx2[i]),py2[i]=min(py2[i-1],yy2[i]);
	for(int i=n;i>=1;i--) lx1[i]=max(lx1[i+1],xx1[i]),ly1[i]=max(ly1[i+1],yy1[i]),lx2[i]=min(lx2[i+1],xx2[i]),ly2[i]=min(ly2[i+1],yy2[i]);
	if(px1[n]<=px2[n] && py1[n]<=py2[n]) t=1ll*(px2[n]-px1[n]+1)*(py2[n]-py1[n]+1);tot=t;
	for(int i=1;i<=n;i++){
		int xx1=max(px1[i-1],lx1[i+1]),xx2=min(px2[i-1],lx2[i+1]),yy1=max(py1[i-1],ly1[i+1]),yy2=min(py2[i-1],ly2[i+1]);
		if(xx2>=xx1 && yy2>=yy1) tot+=1ll*(xx2-xx1+1)*(yy2-yy1+1);
		tot-=t;
	}
	printf("%lld\n",tot);
}

      E

      是一道式子比较恶心的优化Dp,笔者在考试的时候写了很久拿到了68分,题解已经很详细,在这里不再赘述。

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

const int N=2010;
int T,n;
int d[N],p[N];
int f[N][N<<1];
const int mod=998244353;

int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&d[i]);
		bool tf=true;
		for(int i=1;i<=n-1;i++) scanf("%d",&p[i]);p[n]=0;
		for(int i=1;i<=n-1;i++) if((p[i]+d[i+1]-p[i+1])&1) tf=false;
		if(!tf){
			printf("0\n");
			continue;
		}
		for(int i=1;i<=n;i++) for(int j=0;j<=p[i];j++) f[i][j]=0;
		for(int i=0;i<=min(d[1],p[1]);i++) f[1][i]=1;
		for(int i=1;i<n;i++){
			for(int j=0;j<=p[i];j++)
				for(int q=0;q<=d[i+1];q++)
					if(max((p[i]+d[i+1]-p[i+1])/2-min(d[i+1]-q,p[i]-j),0)<=min(min(q,j),(p[i]+d[i+1]-p[i+1])/2)){
						(f[i+1][j+q-2*min(min(q,j),(p[i]+d[i+1]-p[i+1])/2)]+=f[i][j])%=mod;
						(f[i+1][j+q-2*max((p[i]+d[i+1]-p[i+1])/2-min(d[i+1]-q,p[i]-j),0)+2]+=mod-f[i][j])%=mod;
					}
			for(int j=2;j<=p[i+1];j+=2) (f[i+1][j]+=f[i+1][j-2])%=mod;
			for(int j=3;j<=p[i+1];j+=2) (f[i+1][j]+=f[i+1][j-2])%=mod;
		}
		printf("%d\n",f[n][0]);
	}
} 

      F

      这题怎么做呢?

      首先转化为一棵有根树,这样比较好算贡献(我这都没想到)。

      接着对于一个<=D的点,暴力即可,否则对儿子的权值维护一个高维前缀和,发现答案就是该点权值取反的子集和。

      但是这样每次修改维护高维前缀和的时间都是2^m的,发现查询居然只要O(1),想办法均摊。

      我们在维护高维前缀和的时候只把一个权值加到前10位超集上面,然后询问的时候查询后10位的子集和,想一想就知道一对子集对(x,y)会在y前10位+x后10位的这个点被算1遍。至于D的取值,1000即可,因为你会发现再小空间开不下。

      我认为这次比赛严格符合NOIP2018的整体难度,思维清晰,较为自然的题目背景,恰当合适的数据范围,再加上提高区分度的多组数据测试模式,真是一套值得赞叹的好题!

 

# YOLOv5 🚀 requirements # Usage: pip install -r requirements.txt # Base ------------------------------------------------------------------------ gitpython ipython # interactive notebook matplotlib>=3.2.2 numpy>=1.18.5 opencv-python>=4.1.1 Pillow>=7.1.2 psutil # system resources PyYAML>=5.3.1 requests>=2.23.0 scipy>=1.4.1 thop>=0.1.1 # FLOPs computation torch>=1.7.0 # see https://pytorch.org/get-started/locally (recommended) torchvision>=0.8.1 tqdm>=4.64.0 # protobuf<=3.20.1 # https://github.com/ultralytics/yolov5/issues/8012 # Logging --------------------------------------------------------------------- tensorboard>=2.4.1 # clearml>=1.2.0 # comet # Plotting -------------------------------------------------------------------- pandas>=1.1.4 seaborn>=0.11.0 # Export ---------------------------------------------------------------------- # coremltools>=6.0 # CoreML export # onnx>=1.9.0 # ONNX export # onnx-simplifier>=0.4.1 # ONNX simplifier # nvidia-pyindex # TensorRT export # nvidia-tensorrt # TensorRT export # scikit-learn<=1.1.2 # CoreML quantization # tensorflow>=2.4.1 # TF exports (-cpu, -aarch64, -macos) # tensorflowjs>=3.9.0 # TF.js export # openvino-dev # OpenVINO export # Deploy ---------------------------------------------------------------------- # tritonclient[all]~=2.24.0 # Extras ---------------------------------------------------------------------- # mss # screenshots # albumentations>=1.0.3 # pycocotools>=2.0 # COCO mAP # roboflow # ultralytics # HUB https://hub.ultralytics.com
05-25
### YOLOv5 的依赖库及其用途 YOLOv5 是一种高效的实时对象检测框架,其运行需要一系列 Python 库的支持。以下是 YOLOv5 中常见的依赖库以及它们的主要功能: #### 1. **torch** PyTorch 是 YOLOv5 的核心深度学习框架,用于构建和训练神经网络模型[^2]。 它提供了动态计算图支持,使得模型定义更加灵活。 ```python import torch print(torch.__version__) ``` #### 2. **numpy** NumPy 提供了高性能的数组操作能力,广泛用于数据预处理、后处理以及其他数值运算任务[^3]。 ```python import numpy as np arr = np.array([1, 2, 3]) print(arr) ``` #### 3. **opencv-python** OpenCV 被用来加载图像、视频流,并执行各种计算机视觉任务,例如图像增强、颜色转换等[^4]。 ```python import cv2 image = cv2.imread(&#39;example.jpg&#39;) cv2.imshow(&#39;Image&#39;, image) cv2.waitKey(0) ``` #### 4. **matplotlib** Matplotlib 主要用于可视化目的,比如绘制损失曲线或展示检测结果[^5]。 ```python import matplotlib.pyplot as plt plt.plot([1, 2, 3], [4, 5, 6]) plt.show() ``` #### 5. **tqdm** `tqdm` 可以显示进度条,在长时间运行的操作中提供直观反馈[^6]。 ```python from tqdm import tqdm for i in tqdm(range(100)): pass ``` #### 6. **pandas** Pandas 常被用作数据分析工具,特别是在评估阶段整理实验结果时非常有用[^7]。 ```python import pandas as pd df = pd.DataFrame({&#39;A&#39;: [1, 2], &#39;B&#39;: [3, 4]}) print(df) ``` #### 7. **scipy** SciPy 扩展了 NumPy 功能集,增加了更多科学计算方法,可能涉及距离度量或其他统计分析[^8]。 ```python from scipy.spatial.distance import euclidean dist = euclidean([1, 2], [4, 6]) print(dist) ``` #### 8. **tensorboard** TensorBoard 是 PyTorch 集成的一个日志记录工具,允许开发者监控训练过程中的指标变化情况[^9]。 ```bash pip install tensorboard ``` --- ### 总结 以上列举的是 YOLOv5 正常运作所需的关键第三方包集合。每项都有特定职责范围内的贡献,共同保障整个项目顺利实施完成。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值