2020.11.05【NOIP提高A组】模拟 比赛总结

22 篇文章 0 订阅
8 篇文章 0 订阅

比赛地址

https://gmoj.net/senior/#contest/home/3248

题目

gmoj 6839. 【2020.11.5提高组模拟】淘淘蓝蓝喜欢 01串
gmoj 6840. 【2020.11.5提高组模拟】铲雪(snow)
gmoj 6841. 【2020.11.5提高组模拟】淘淘蓝蓝之树 林
gmoj 6842. 【2020.11.5提高组模拟】淘淘蓝蓝之扮猪吃愉 悦

总结

这次是CSP复赛前的最后一场模拟赛了,但我却考得非常差。

T1

很简单的一道题,发现对于操作的第二步而言,块的长度不重要。因此操作的第一步在长度大于1的块中删除即可,而删除靠前的块中的元素一定是最优的。

手玩了几个数据后,我就觉得这题OK了,于是打第二题去了。

结果成绩出来后傻眼了——WA 30!!!

检查后发现问题是这样的:我用两个指针向右扫,一个表示当前最靠前的是哪个块,另一个维护最靠前的长度大于1的块。但是我没有强制要求第二个指针必须在第一个指针后面!!!

T2

这题想了不久就会做了。

发现如果一行上的积雪被清理得可以走了,这整个行的位置都是可以到达的,也就是可以到达任意的可走的列。

考虑怎么从起点走到终点,分3种讨论:

  1. 起点和终点之间的行都是可走的,直接走最短的路径即可;
  2. 起点的行和终点的列是可走的,从起点顺着行走到行、列的交点,再顺着列走到终点即可,这也是最短的路径;
  3. 起点和终点的行是可走的,那么在选择一个列 l l l,使得 ∣ y s t − l ∣ + ∣ y e d − l ∣ |y_{st}-l|+|y_{ed}-l| ystl+yedl最小。

走起点的列的情况也是同理。
这个用两棵线段树维护起来很方便。

打得很顺(这个键盘真是舒服),敲了 3000 b y t e s + 3000bytes+ 3000bytes+也不觉得累,测了几个数据后觉得过了,就看后面的题目去了。

结果成绩出来之和更傻眼了——WA 0?!!

后来检查了一下,是两个问题导致的:

  1. 有一个变量rx打成了ly
  2. 在处理第3种情况时,没有判断这个列是否存在。

T3

没想到怎么做。
一开始的想法是先把与X八联通的点全部取出来,然后问题就是怎么把这条链压缩得短一些(比如这条链上x到y之间的距离大于两点间的切比雪夫距离时,就把这两个点之间的路径压缩一下)

但是这样子还是做不了。

想了好久还是没有想出来,见时间不够了,就打T4 A=0的部分分去了。

题解:https://blog.csdn.net/huangzihaoal/article/details/109521582

T4

A=0的数据显然power越大,最后得分越多。因此二分+树上DP即可。

但是没有打对,最后加上n=1的数据拿了40分。

题解:https://blog.csdn.net/huangzihaoal/article/details/109520644

总结

这次比赛考得奇烂无比,我觉得原因有两点:

  1. 我T1、T2没有打对拍。就算是一道简单的题,只要正解不是暴力模拟,都应该要对拍。想要省下那对拍的十多分钟,分数可能就会少上几十分;
  2. 我T3没有下定决心拿40分暴力分。如果想了好久都没有头绪,就应该直接暴力拿部分分。最后的对决,不在于有没有切某一道难题,而在于部分分拿了多少!

祝CSP RP++!

CODE

T1

#include<cstdio>
using namespace std;
#define N 100005
char s[N];int a[N];
int main()
{
	freopen("str.in","r",stdin);
	freopen("str.out","w",stdout);
	int t,n,m,ans;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%s",&n,s+1);
		m=a[1]=1,ans=0;
		for(int i=2;i<=n;++i)
		{
			if(s[i]!=s[i-1]) a[++m]=0;
			++a[m];
		}
		for(int i=1,j=1;i<=m;++i)
		{
			++ans;
			if(j<i) j=i;
			while(j<m&&a[j]==1) ++j;
			if(a[j]==1) ++i;
			else --a[j];
		}
		printf("%d\n",ans);
	}
	return 0;
}

T2

#include<cstdio>
using namespace std;
#define print {printf("%d\n",dis(s,t));continue;}
#define rson k<<1|1
#define lson k<<1
#define M 5000005
#define N 1000005
inline int mymin(int x,int y){return x<y?x:y;}
inline int mymax(int x,int y){return x>y?x:y;}
struct line
{
	int a[N],min[M],max[M];
	void modify(int k,int l,int r,int x)
	{
		if(l==r) min[k]=max[k]=a[l];
		else
		{
			int mid=l+r>>1;
			if(x<=mid) modify(lson,l,mid,x);
			else modify(rson,mid+1,r,x);
			min[k]=mymin(min[lson],min[rson]);
			max[k]=mymax(max[lson],max[rson]);
		}
	}
	int qry(int k,int l,int r,int x,int y)
	{
		if(l==x&&r==y) return min[k];
		int mid=l+r>>1;
		if(y<=mid) return qry(lson,l,mid,x,y);
		if(x>mid) return qry(rson,mid+1,r,x,y);
		return mymin(qry(lson,l,mid,x,mid),qry(rson,mid+1,r,mid+1,y));
	}
	int get_max(int k,int l,int r,int num)
	{
		if(max[k]<num) return 0;
		if(l==r) return l;
		int mid=l+r>>1,res=get_max(rson,mid+1,r,num);
		return res?res:get_max(lson,l,mid,num);
	}
	int find_max(int k,int l,int r,int x,int y,int num)
	{
		if(max[k]<num) return 0;
		if(l==x&&r==y) return get_max(k,l,r,num);
		int mid=l+r>>1;
		if(y<=mid) return find_max(lson,l,mid,x,y,num);
		if(x>mid) return find_max(rson,mid+1,r,x,y,num);
		int res=find_max(rson,mid+1,r,mid+1,y,num);
		return res?res:find_max(lson,l,mid,x,mid,num);
	}
	int get_min(int k,int l,int r,int num)
	{
		if(max[k]<num) return 0;
		if(l==r) return l;
		int mid=l+r>>1,res=get_min(lson,l,mid,num);
		return res?res:get_min(rson,mid+1,r,num);
	}
	int find_min(int k,int l,int r,int x,int y,int num)
	{
		if(max[k]<num) return 0;
		if(l==x&&r==y) return get_min(k,l,r,num);
		int mid=l+r>>1;
		if(y<=mid) return find_min(lson,l,mid,x,y,num);
		if(x>mid) return find_min(rson,mid+1,r,x,y,num);
		int res=find_min(lson,l,mid,x,mid,num);
		return res?res:find_min(rson,mid+1,r,mid+1,y,num);
	}
}a,b;
struct node{int x,y;}s,t;
inline int abs(int x){return x<0?-x:x;}
inline int dis(node x,node y){return abs(x.x-y.x)+abs(x.y-y.y);}
int main()
{
	freopen("snow.in","r",stdin);
	freopen("snow.out","w",stdout);
	int n,m,q,opt,x,k,lx,rx,ly,ry,ans1,ans2,ans,tmp,res1,res2;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=q;++i)
	{
		scanf("%d",&opt);
		if(opt==1) scanf("%d",&x),a.a[x]=i,a.modify(1,1,n,x);
		else if(opt==2) scanf("%d",&x),b.a[x]=i,b.modify(1,1,m,x);
		else
		{
			scanf("%d%d%d%d%d",&s.x,&s.y,&t.x,&t.y,&k);
			k=i-k,lx=mymin(s.x,t.x),rx=mymax(s.x,t.x);
			ly=mymin(s.y,t.y),ry=mymax(s.y,t.y),ans=-1;
			if(a.a[s.x]>=k)
			{
				if(b.a[t.y]>=k) print
				if(a.qry(1,1,n,lx,rx)>=k) print
				if(a.a[t.x]>=k)
				{
					if(b.find_max(1,1,m,ly,ry,k)) print
					ans1=ans2=0;
					if(ly>1)
					{
						res1=b.find_max(1,1,m,1,ly-1,k);
						ans1=res1?ly-res1:0;
					}
					if(ry<m)
					{
						res2=b.find_min(1,1,m,ry+1,m,k);
						ans2=res2?res2-ry:0;
					}
					if(ans1) ans=(ans2?mymin(ans1,ans2):ans1)*2+dis(s,t);
					else if(ans2) ans=ans2*2+dis(s,t);
				}
			}
			if(b.a[s.y]>=k)
			{
				if(a.a[t.x]>=k) print
				if(b.qry(1,1,m,ly,ry)>=k) print
				if(b.a[t.y]>=k)
				{
					if(a.find_max(1,1,n,lx,rx,k)) print
					ans1=ans2=0;
					if(lx>1)
					{
						res1=a.find_max(1,1,n,1,lx-1,k);
						ans1=res1?lx-res1:0;
					}
					if(rx<n)
					{
						res2=a.find_min(1,1,n,rx+1,n,k);
						ans2=rx<n&&res2?res2-rx:0;
					}
					tmp=0;
					if(ans1) tmp=(ans2?mymin(ans1,ans2):ans1)*2+dis(s,t);
					else if(ans2) tmp=ans2*2+dis(s,t);
					if(tmp) ans=ans<0?tmp:mymin(ans,tmp);
				}
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

T3

#include<cstdio>
#include<cstring>
using namespace std;
#define M 4000005
#define N 2005
const int dx[8]={1,1,1,0,0,-1,-1,-1},dy[8]={0,1,-1,1,-1,0,1,-1};
char a[N][N];int f[N][N],data[M][2],n,m;
inline void bfs(int stx,int sty)
{
	int x,y,xx,yy,head=0,tail=1;
	data[1][0]=stx,data[1][1]=sty;
	memset(f,0x3f,sizeof f);
	f[stx][sty]=0;
	while(head<tail)
	{
		x=data[++head][0],y=data[head][1];
		for(int i=0;i<8;++i)
		{
			xx=x+dx[i],yy=y+dy[i];
			if(xx&&yy&&xx<=n&&yy<=m&&a[xx][yy]=='.'&&f[xx][yy]>f[x][y]+1)
			{
				f[xx][yy]=f[x][y]+1;
				data[++tail][0]=xx,data[tail][1]=yy;
			}
		}
	}
}
int main()
{
	freopen("forest.in","r",stdin);
	freopen("forest.out","w",stdout);
	int stx,sty,x=0,y=0,ans=999999999,up,down;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) scanf("%s",a[i]+1);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(a[i][j]=='*'){stx=i,sty=j;goto out;}
	out:
	for(int j=1;j<=m;++j)
		for(int i=1;i<=n;++i)
			if(a[i][j]=='X'){x=i,y=j;goto judge;}
	judge:
	if(stx==x&&sty<y)
	{
		for(int j=1;j<=m;++j)
			for(int i=1;i<=n;++i)
				if(a[i][j]=='X'){x=i,y=j;goto mark;}
		mark:
		for(int i=y+1;i<=m;++i) a[x][i]='+';
	}
	else for(int i=1;i<y;++i) a[x][i]='+';
	bfs(stx,sty);
	for(int i=1;i<=m;++i) if(a[x][i]=='+')
	{
		up=f[x-1][i];
		if(i>1&&f[x-1][i-1]<up) up=f[x-1][i-1];
		if(i<m&&f[x-1][i+1]<up) up=f[x-1][i+1];
		down=f[x+1][i];
		if(i>1&&f[x+1][i-1]<down) down=f[x+1][i-1];
		if(i<m&&f[x+1][i+1]<down) down=f[x+1][i+1];
		if(up+down+2<ans) ans=up+down+2;
	}
	printf("%d\n",ans);
	return 0;
}

T4

#include<cmath>
#include<cstdio>
using namespace std;
typedef long double LF;
#define inf 500000
#define M 200005
#define N 100005
#define e 1e-8
int fir[N],to[M],nex[M],a[N],b[N],deg[N],son[N][2],A,p0,p1,s;
//a:power; b:point
LF f[N],g[N][2],maxx,P;
inline void inc(int x,int y)
{
	++deg[x],++deg[y];
	to[++s]=y,nex[s]=fir[x],fir[x]=s;
	to[++s]=x,nex[s]=fir[y],fir[y]=s;
}
inline int sig(LF x){return x==0?0:(x<0?-1:1);}
inline LF calc(int k,LF power,LF point)
{return 2*sig(power-a[k])*(sqrt(abs(power-a[k])+1)-1)-
A*sig(point-b[k])*(sqrt(abs(point-b[k])+1)-1);}
void dfs(int k,int fa)
{
	g[k][0]=g[k][1]=-inf,son[k][0]=son[k][1]=0;
	if(k>1&&deg[k]==1) return;
	for(int i=fir[k];i;i=nex[i]) if(to[i]!=fa)
	{
		dfs(to[i],k);
		if(f[to[i]]>g[k][0])
			g[k][1]=g[k][0],son[k][1]=son[k][0],
			g[k][0]=f[to[i]],son[k][0]=to[i];
		else if(f[to[i]]>g[k][1]) g[k][1]=f[to[i]],son[k][1]=to[i];
	}
	f[k]=g[k][0]+calc(k,P,g[k][0]);
}
void rotate(int k,int fa)
{
	if(deg[k]==1&&f[k]>maxx) maxx=f[k];
	LF gk[2],sk[2],fk=f[k],gi[2],si[2],fi;
	gk[0]=g[k][0],sk[0]=son[k][0];
	gk[1]=g[k][1],sk[1]=son[k][1];
	for(int i=fir[k];i;i=nex[i]) if(to[i]!=fa)
	{
		gi[0]=g[to[i]][0],si[0]=son[to[i]][0];
		gi[1]=g[to[i]][1],si[1]=son[to[i]][1],fi=f[to[i]];
		if(to[i]==son[k][0]) f[k]=deg[k]==1?p0+calc(k,P,p0):g[k][1]+calc(k,P,g[k][1]);
		if(f[k]>g[to[i]][0])
		{
			g[to[i]][1]=g[to[i]][0],son[to[i]][1]=son[to[i]][0];
			g[to[i]][0]=f[k],son[to[i]][0]=k;
			f[to[i]]=f[k]+calc(to[i],P,f[k]);
		}
		else if(f[k]>g[to[i]][1]) g[to[i]][1]=f[k],son[to[i]][1]=k;
		rotate(to[i],k);
		g[to[i]][0]=gi[0],son[to[i]][0]=si[0];
		g[to[i]][1]=gi[1],son[to[i]][1]=si[1];
		g[k][0]=gk[0],son[k][0]=sk[0];
		g[k][1]=gk[1],son[k][1]=sk[1];
		f[k]=fk,f[to[i]]=fi;
	}
}
int main()
{
	freopen("pigeatyy.in","r",stdin);
	freopen("pigeatyy.out","w",stdout);
	LF l=-inf,r=inf,mid,ans=0;
	int test,n,x,y;
	scanf("%d%d%d%d%d",&test,&n,&p0,&p1,&A);
	for(int i=1;i<n;++i) scanf("%d%d",&x,&y),inc(x,y);
	for(int i=1;i<=n;++i) scanf("%d%d",a+i,b+i);
	while(l<=r)
	{
		mid=(l+r)/2;
		if(n==1) maxx=p0+calc(1,mid,p0);
		else
		{
			for(int i=1;i<=n;++i)
				if(deg[i]==1)
				{
					f[i]=p0+calc(i,mid,p0);
					if(f[i]>=p1){r=mid-e,ans=mid;continue;}
				}
				else f[i]=0;
			P=mid,dfs(1,0);
			maxx=0,rotate(1,0);
		}
		if(maxx>=p1) r=mid-e,ans=mid;
		else l=mid+e;
	}
	printf("%.6LF\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值