比赛地址
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种讨论:
- 起点和终点之间的行都是可走的,直接走最短的路径即可;
- 起点的行和终点的列是可走的,从起点顺着行走到行、列的交点,再顺着列走到终点即可,这也是最短的路径;
- 起点和终点的行是可走的,那么在选择一个列 l l l,使得 ∣ y s t − l ∣ + ∣ y e d − l ∣ |y_{st}-l|+|y_{ed}-l| ∣yst−l∣+∣yed−l∣最小。
走起点的列的情况也是同理。
这个用两棵线段树维护起来很方便。
打得很顺(这个键盘真是舒服),敲了 3000 b y t e s + 3000bytes+ 3000bytes+也不觉得累,测了几个数据后觉得过了,就看后面的题目去了。
结果成绩出来之和更傻眼了——WA 0?!!
后来检查了一下,是两个问题导致的:
- 有一个变量
rx
打成了ly
; - 在处理第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
总结
这次比赛考得奇烂无比,我觉得原因有两点:
- 我T1、T2没有打对拍。就算是一道简单的题,只要正解不是暴力模拟,都应该要对拍。想要省下那对拍的十多分钟,分数可能就会少上几十分;
- 我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&°[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;
}