『模拟赛』CSP提高组模拟1
Rank
A.最短路
洛谷原题 [USACO09DEC] Cow Toll Paths G
一眼 Floyd,但没眼出来要跑好几遍。。
赛时思路上是开一个二维结构体存最短路和路上最大点权,判断若当前未联通或联通但总花费高于更新后总花费就更新。
没有考虑到一种较极限的情况:假设目标起终点为
所以简单的解决办法是多跑几遍。
考虑正解,发现上述方法错误的原因在于点权的判断,思考一下得到先更新点权小的点就不会造成更新紊乱的情况。所以先对点权排序并记录原序列,Floyd 跑的
距离
总答案转移方程为:
赛时 code( )
这个想过就复制几遍 Floyd 部分就行了
赛时唐了,以为 0x3f3f3f3f
会出问题,忘了开的是 long long
了,然后就初始化的 -1。
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(int (x)=(y);(x)>=(z);(x)--)
#define fuck printf(";;;;;;;;\n");
using namespace std;
typedef long long ll;
#define lx int
inline lx qr()
{
char ch=getchar();lx x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=1e4+5;
int n,m,q;
int v[305];
struct rmm
{
ll d=-1;
ll maxx=-1;
}dh[305][305];
int qs[N],qt[N];
namespace Wisadel
{
bool Wck(int x,int y,int z)
{
if(dh[y][z].d!=-1&&dh[x][z].d!=-1)
{
if(dh[x][y].d==-1) return 1;
else if(dh[x][y].d+dh[x][y].maxx>dh[y][z].d+dh[z][x].d+max(dh[y][z].maxx,dh[z][x].maxx))
return 1;
}
return 0;
}
short main()
{
freopen("path.in","r",stdin),freopen("path.out","w",stdout);
n=qr,m=qr,q=qr;
fo(i,1,n) v[i]=qr,dh[i][i].d=0,dh[i][i].maxx=v[i];
fo(i,1,m)
{
int a=qr,b=qr,c=qr;
if(dh[a][b].d==-1||c<dh[a][b].d)
dh[a][b].d=dh[b][a].d=c,
dh[a][b].maxx=dh[b][a].maxx=max(v[a],v[b]);
}
fo(k,1,n)
fo(i,1,n)
fo(j,1,n)
if(Wck(i,j,k))
dh[i][j].d=dh[i][k].d+dh[k][j].d,
dh[i][j].maxx=max(dh[i][k].maxx,dh[k][j].maxx);
fo(i,1,q)
{
int a=qr,b=qr;
if(dh[a][b].d==-1) printf("-1\n");
else printf("%lld\n",dh[a][b].d+dh[a][b].maxx);
}
return Ratio;
}
}
int main(){return Wisadel::main();}
正解
const int Ratio=0;
const int N=305;
int n,m,q;
struct rmm
{
int v,id;
}c[N];
bool cmp(rmm a,rmm b)
{
return a.v<b.v;
}
ll dh[N][N],ans[N][N];
namespace Wisadel
{
short main()
{
freopen("path.in","r",stdin),freopen("path.out","w",stdout);
n=qr,m=qr,q=qr;
memset(dh,0x3f,sizeof dh);
memset(ans,0x3f,sizeof ans);
fo(i,1,n) c[i].v=qr,dh[i][i]=0,c[i].id=i;
sort(c+1,c+1+n,cmp);
fo(i,1,m)
{
int a=qr,b=qr,c=qr;
if(c<dh[a][b]) dh[a][b]=dh[b][a]=c;
}
fo(k,1,n)
fo(i,1,n)
fo(j,1,n)
dh[c[i].id][c[j].id]=min(dh[c[i].id][c[j].id],dh[c[i].id][c[k].id]+dh[c[k].id][c[j].id]),
ans[c[i].id][c[j].id]=min(ans[c[i].id][c[j].id],dh[c[i].id][c[j].id]+max(c[i].v,max(c[j].v,c[k].v)));
fo(i,1,q)
{
int a=qr,b=qr;
if(ans[a][b]>=1e18) printf("-1\n");
else printf("%lld\n",ans[a][b]);
}
return Ratio;
}
}
int main(){return Wisadel::main();}
B.方格取数
洛谷原题[POI2008] KUP-Plot purchase
赛时写了暴搜,但是假了好像,重评两次只有
首先输入时就能判的点,如果某点权值
所以只能选
用二维前缀和维护一下,每次求和复杂度为
赛时码太唐了,没意义不放了。
Code:
const int Ratio=0;
const int N=2005;
int n,top;
ll k,sum,d[N][N];
ll qz[N][N];
int up[N],st[N];
namespace Wisadel
{
ll Ws(int li,int lj,int ri,int rj)
{
return qz[ri][rj]-qz[li][rj]-qz[ri][lj]+qz[li][lj];
}
short main()
{
freopen("matrix.in","r",stdin),freopen("matrix.out","w",stdout);
n=qr,k=qr;
fo(i,1,n)
fo(j,1,n) d[i][j]=qr;
fo(i,1,n)
fo(j,1,n) qz[i][j]=qz[i][j-1]+d[i][j];
fo(i,1,n)
fo(j,1,n) qz[i][j]+=qz[i-1][j];
fo(i,1,n)
fo(j,1,n+1)
{
if(d[i][j]<=2*k&&j<=n)
{
up[j]++;
if(d[i][j]>=k)
{
printf("%d %d %d %d\n",i,j,i,j);
return Ratio;
}
}
else up[j]=0;
while(top&&up[st[top]]>=up[j])
{
int lj=st[top-1],rj=j-1;
int li=i-up[st[top]];
if(Ws(li,lj,i,rj)>=k)
{
while(Ws(li,lj,i,rj)>2*k)
{
if(Ws(li,lj,li+1,rj)>2*k)
{
while(Ws(li,lj,li+1,rj)>2*k)++lj;
printf("%d %d %d %d\n",li+1,lj+1,li+1,rj);
return Ratio;
}
li++;
}
printf("%d %d %d %d\n",li+1,lj+1,i,rj);
return Ratio;
}
top--;
}
if(j<=n) st[++top]=j;
}
printf("-1\n");
return Ratio;
}
}
int main(){return Wisadel::main();}
C.数组
洛谷原题[CF1114F] Please, another Queries on Array?
看到线段树本来都力了,昨天刚好打了线段树维护区间积的板子,结果遇到了已经忘得差不多了的欧拉函数。
点击撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
好想撅了欧拉
就只记得求单个欧拉函数的板子,然后就唐唐地求完积再求值,然后样例就爆了,然后就把取模删了,然后全 WA 了。
正解如下:
因为欧拉函数不可取模,所以我们直接把它拆开。
Code:
const int N=4e5+5;
const ll mod=1e9+7;
ll n,q;
ll a[N],c[N];
ll prime[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293};
namespace Wisadel
{
struct rmm
{
ll w,mark;
bitset<70>p,markp;
}t[N<<2],T;
ll Wqp(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1) res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
void Wpushup(int rt)
{
t[rt].w=t[ls].w*t[rs].w%mod;
t[rt].p=t[ls].p|t[rs].p;
}
void Wpushdown(int rt,int l,int r)
{
if(t[rt].mark!=1)
{
t[ls].mark=t[ls].mark*t[rt].mark%mod;
t[rs].mark=t[rs].mark*t[rt].mark%mod;
t[ls].w=t[ls].w*Wqp(t[rt].mark,mid-l+1)%mod;
t[rs].w=t[rs].w*Wqp(t[rt].mark,r-mid)%mod;
t[ls].p|=t[rt].markp;
t[rs].p|=t[rt].markp;
t[ls].markp|=t[rt].markp;
t[rs].markp|=t[rt].markp;
t[rt].mark=1;
t[rt].markp.reset();
}
}
void Wbuild(int rt,int l,int r)
{
t[rt].mark=1;
if(l==r)
{
t[rt].w=a[l];
for(ll i=1;i<=62&&prime[i]<=a[l];i++)
t[rt].p[i]=(a[l]%prime[i]==0);
return;
}
Wbuild(ls,l,mid),Wbuild(rs,mid+1,r);
Wpushup(rt);
}
void Wupd(int rt,int l,int r,int x,int y,int k)
{
if(x<=l&&r<=y)
{
t[rt].w=t[rt].w*Wqp(k,r-l+1)%mod;
t[rt].mark=t[rt].mark*k%mod;
fo(i,1,62)
t[rt].p[i]=t[rt].p[i]|(k%prime[i]==0),
t[rt].markp[i]=t[rt].markp[i]|(k%prime[i]==0);
return;
}
Wpushdown(rt,l,r);
if(x<=mid) Wupd(ls,l,mid,x,y,k);
if(y>mid) Wupd(rs,mid+1,r,x,y,k);
Wpushup(rt);
}
rmm Wq(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return t[rt];
Wpushdown(rt,l,r);
rmm ans,num;
ans.w=1,ans.p.reset();
if(x<=mid)
{
num=Wq(ls,l,mid,x,y);
ans.w=ans.w*num.w%mod;
ans.p|=num.p;
}
if(y>mid)
{
num=Wq(rs,mid+1,r,x,y);
ans.w=ans.w*num.w%mod;
ans.p|=num.p;
}
return ans;
}
short main()
{
freopen("array.in","r",stdin),freopen("array.out","w",stdout);
n=qr,q=qr;
fo(i,1,n) a[i]=qr;
fo(i,1,62) c[i]=(prime[i]-1)*Wqp(prime[i],mod-2)%mod;
Wbuild(1,1,n);
fo(i,1,q)
{
int op=qr,a=qr,b=qr,cc;
if(op==1) cc=qr,Wupd(1,1,n,a,b,cc);
else
{
T=Wq(1,1,n,a,b);
fo(j,1,62)
if(T.p[j]==1)
T.w=T.w*c[j]%mod;
printf("%lld\n",T.w);
}
}
return Ratio;
}
}
int main(){return Wisadel::main();}
D.树
看到给部分分给得很详细啊,果断打了四个 namespace
,结果把最简单的第二个 Subtask WA 了。
Subtask1:(也就只会这个了逝罢),然后暴力寻找每次停留点,加和求出答案即可。
Subtask3:(我认为)最简单的一个。链的性质很好啊,在这道题等价于知道了两点的序号就获得了两点的路径长,while
循环不断跳跃即可。
Subtask2&4:利用数据水的特性,直接利用树链剖分和 LCA 暴力就过了,恼,赛时就没想暴力跑,挂 。
Code from namespace狂人
const int N=5e4+5;
int n;
int a[N],b[N],c[N];
int hh[N],to[N<<1],ne[N<<1],dis[N<<1],cnt;
bool subtask2=1,subtask3=1;
namespace Wisadeltask1
{
int dh[1005][1005];
short main()
{
memset(dh,0x3f,sizeof dh);
fo(i,1,n) a[i]=qr;
fo(i,1,n-1)
{
int a=qr,b=qr;
dh[a][b]=dh[b][a]=1;
}
fo(i,1,n) b[i]=qr,dh[i][i]=0;
fo(i,1,n-1) c[i]=qr;
fo(k,1,n)
fo(i,1,n)
fo(j,1,n)
dh[i][j]=min(dh[i][j],dh[i][k]+dh[k][j]);
fo(i,1,n-1)
{
int u=b[i],v=b[i+1];
int len=dh[u][v];
int tim=len/c[i],ans=a[u];
fo(tt,1,tim)
{
fo(j,1,n)
if(dh[u][j]==c[i]&&dh[u][j]+dh[j][v]==dh[u][v])
{
u=j;ans+=a[u];
break;
}
}
printf("%d\n",ans);
}
return Ratio;
}
}
namespace Wisadeltask2
{
int dep[N],fx[17][N],zu[N],bigson[N],siz[N];
void Wdfs(int u,int fa)
{
fx[0][u]=fa,dep[u]=dep[fa]+1;
for(int i=hh[u];i!=-1;i=ne[i])
{
int v=to[i];
if(v==fa) continue;
Wdfs(v,u);
}
}
int Wlca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
fu(i,16,0)
if(dep[u]-dep[v]>=(1<<i))
u=fx[i][u];
fu(i,16,0)
if(fx[i][u]!=fx[i][v])
u=fx[i][u],v=fx[i][v];
if(u==v) return u;
else return fx[0][u];
}
int Wto(int u,int stp)
{
int st=0;
while(stp)
{
if(stp&1) u=fx[st][u];
stp>>=1;
st++;
}
return u;
}
int Wsol(int u,int v,int len)
{
int ans=a[u]+a[v],rt=Wlca(u,v);
while(dep[u]-dep[rt]>=len)
u=Wto(u,len),ans+=a[u];
while(dep[v]-dep[rt]>=len)
v=Wto(v,len),ans+=a[v];
if(u==v) ans-=a[u];
return ans;
}
short main()
{
Wdfs(1,0);
fo(i,1,16)
fo(j,1,n)
fx[i][j]=fx[i-1][fx[i-1][j]];
fo(i,1,n-1)
printf("%d\n",Wsol(b[i],b[i+1],c[i]));
return Ratio;
}
}
namespace Wisadeltask3
{
short main()
{
fo(i,1,n-1)
{
int u,v,ans=0;
if(b[i+1]<b[i]) u=b[i+1],v=b[i];
else u=b[i],v=b[i+1];
ans=a[u];
while(u!=v) u+=c[i],ans+=a[u];
printf("%d\n",ans);
}
return Ratio;
}
}
namespace Wisadel
{
void Wadd(int u,int v)
{
to[++cnt]=v;
dis[cnt]=1;
ne[cnt]=hh[u];
hh[u]=cnt;
}
short main()
{
freopen("tree.in","r",stdin),freopen("tree.out","w",stdout);
memset(hh,-1,sizeof hh);
n=qr;
if(n<=1000) return Wisadeltask1::main();
fo(i,1,n)
{
a[i]=qr;
if(a[i]!=1) subtask2=0;
}
fo(i,1,n-1)
{
int u=qr,v=qr;
if(v!=u+1) subtask3=0;
Wadd(u,v),Wadd(v,u);
}
fo(i,1,n) b[i]=qr;
fo(i,1,n-1) c[i]=qr;
if(subtask3) return Wisadeltask3::main();
return Wisadeltask2::main();
}
}
int main(){return Wisadel::main();}
完结撒花~
picture from hzoi_Shadow
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探