2025多校冲刺省选模拟赛9
2025多校冲刺省选模拟赛9
A. 鸬鹚
-
部分分
-
顺次迭代,并查集优化不明显。
-
判断矩形相交时在特判掉包含后可以直接代入四个角进行判断。
点击查看代码
struct node { int x1,x2,y1,y2; node operator + (const node &another) const { return (node){min(x1,another.x1), max(x2,another.x2), min(y1,another.y1), max(y2,another.y2)}; } }f[2][100010]; bool cmp(node a,node b) { if(a.x1!=b.x1) return a.x1<b.x1; if(a.x2!=b.x2) return a.x2<b.x2; if(a.y1!=b.y1) return a.y1<b.y1; return a.y2<b.y2; } struct DSU { int fa[100010]; void init(int n) { for(int i=1;i<=n;i++) fa[i]=i; } int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void merge(int x,int y,int op) { x=find(x); y=find(y); if(x!=y) { fa[y]=x; f[op][x]=f[op][x]+f[op][y]; } } }D; int cnt[2]; bool check(int x1,int y1,int x2,int y2,int _x1,int _y1,int _x2,int _y2) { if(x1<_x1) { swap(x1,_x1); swap(y1,_y1); swap(x2,_x2); swap(y2,_y2); } return (x1<_x2&&((_y1<=y1&&y1<_y2)||(_y1<y2&&y2<=_y2)||(y1<=_y1&&_y2<=y2))); } int main() { #define Isaac #ifdef Isaac freopen("cormorant.in","r",stdin); freopen("cormorant.out","w",stdout); #endif int n,flag,i,j,op=0; cin>>n; cnt[op]=n; for(i=1;i<=n;i++) cin>>f[op][i].x1>>f[op][i].x2>>f[op][i].y1>>f[op][i].y2; for(flag=1;flag==1;op^=1) { flag=cnt[op^1]=0; D.init(cnt[op]); for(i=1;i<=cnt[op];i++) { int x=D.find(i); for(j=i+1;j<=cnt[op];j++) { if(check(f[op][x].x1,f[op][x].y1,f[op][x].x2,f[op][x].y2, f[op][j].x1,f[op][j].y1,f[op][j].x2,f[op][j].y2)==true) { flag=1; D.merge(x,j,op); } } } for(i=1;i<=cnt[op];i++) { if(D.fa[i]==i) { cnt[op^1]++; f[op^1][cnt[op^1]]=f[op][i]; } } } op^=1; sort(f[op]+1,f[op]+1+cnt[op],cmp); cout<<cnt[op]<<endl; for(i=1;i<=cnt[op];i++) cout<<f[op][i].x1<<" "<<f[op][i].x2<<" "<<f[op][i].y1<<" "<<f[op][i].y2<<endl; return 0; }
-
-
正解
- 瓶颈在于判断合并时难以钦定一个次数较少的顺序。即使是类似
的过程也无法处理。 - 以
为线段树的下标,不断将矩形扔到根链的节点上。插入的时候先将能合并的合并掉(删除原来的矩形),在末尾添加本次加入的矩形。 - 暴力遍历整个链表不可接受,需要进一步优化:先将矩形按照
排序使得在不相交时直接退出;为减少重复合并次数影响后续便利,对矩形进行当前弧优化使得只合并一次。 - 具体实现时可以将
先进行 简化判断矩形相交的限制条件。
点击查看代码
struct node { int x1,x2,y1,y2; node operator + (const node &another) const { return (node){min(x1,another.x1), max(x2,another.x2), min(y1,another.y1), max(y2,another.y2)}; } }a[100010]; int d[200010],vis[200010]; bool cmp1(node a,node b) { return a.y2<b.y2; } bool cmp2(node a,node b) { if(a.x1!=b.x1) return a.x1<b.x1; if(a.x2!=b.x2) return a.x2<b.x2; if(a.y1!=b.y1) return a.y1<b.y1; return a.y2<b.y2; } bool check(int x,int y) { return a[x].y2>=a[y].y1&&a[y].y2>=a[x].y1; } struct SMT { struct SegmentTree { vector<int>all,part; }tree[800010]; #define lson(rt) (rt<<1) #define rson(rt) (rt<<1|1) void update(int rt,int l,int r,int x,int y,int id) { tree[rt].part.push_back(id); if(x<=l&&r<=y) { tree[rt].all.push_back(id); return; } int mid=(l+r)/2; if(x<=mid) update(lson(rt),l,mid,x,y,id); if(y>mid) update(rson(rt),mid+1,r,x,y,id); } bool del(vector<int>&v,int id) { int flag=0; while(v.empty()==0&&(vis[v.back()]==1||check(v.back(),id)==true)) { if(vis[v.back()]==0) { vis[v.back()]=1; a[id]=a[id]+a[v.back()]; flag=1; } v.pop_back(); } return flag; } bool query(int rt,int l,int r,int x,int y,int id) { if(del(tree[rt].all,id)==true) return true; if(x<=l&&r<=y) return del(tree[rt].part,id); int mid=(l+r)/2; if(y<=mid) return query(lson(rt),l,mid,x,y,id); if(x>mid) return query(rson(rt),mid+1,r,x,y,id); return query(lson(rt),l,mid,x,y,id)|query(rson(rt),mid+1,r,x,y,id); } }T; int main() { #define Isaac #ifdef Isaac freopen("cormorant.in","r",stdin); freopen("cormorant.out","w",stdout); #endif int n,m=0,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i].x1>>a[i].x2>>a[i].y1>>a[i].y2; a[i].x1++; a[i].y1++; d[0]++; d[d[0]]=a[i].x1; d[0]++; d[d[0]]=a[i].x2; } sort(a+1,a+1+n,cmp1); sort(d+1,d+1+d[0]); d[0]=unique(d+1,d+1+d[0])-(d+1); for(i=1;i<=n;i++) { a[i].x1=lower_bound(d+1,d+1+d[0],a[i].x1)-d; a[i].x2=lower_bound(d+1,d+1+d[0],a[i].x2)-d; while(T.query(1,1,d[0],a[i].x1,a[i].x2,i)==true); T.update(1,1,d[0],a[i].x1,a[i].x2,i); } for(i=1;i<=n;i++) { if(vis[i]==0) { m++; a[m]=a[i]; } } sort(a+1,a+1+m,cmp2); cout<<m<<endl; for(i=1;i<=m;i++) cout<<d[a[i].x1]-1<<" "<<d[a[i].x2]<<" "<<a[i].y1-1<<" "<<a[i].y2<<endl; return 0; }
- 瓶颈在于判断合并时难以钦定一个次数较少的顺序。即使是类似
B. 雪雀
-
部分分
:暴力跑 。
点击查看代码
const ll p=1000000007,dx[4]={0,0,1,-1},dy[4]={-1,1,0,0}; ll a[4][200010],dis[4][200010],vis[4][200010],m; struct quality { ll x,y,dis; bool operator < (const quality &another) const { return dis>another.dis; } }; void dijkstra(ll sx,ll sy) { for(ll i=1;i<=3;i++) { for(ll j=1;j<=m;j++) { dis[i][j]=0x3f3f3f3f3f3f3f3f; vis[i][j]=0; } } priority_queue<quality>q; dis[sx][sy]=a[sx][sy]; q.push((quality){sx,sy,dis[sx][sy]}); while(q.empty()==0) { ll x=q.top().x,y=q.top().y; q.pop(); if(vis[x][y]==0) { vis[x][y]=1; for(ll i=0;i<=3;i++) { ll nx=x+dx[i],ny=y+dy[i]; if(1<=nx&&nx<=3&&1<=ny&&ny<=m&&dis[nx][ny]>dis[x][y]+a[nx][ny]) { dis[nx][ny]=dis[x][y]+a[nx][ny]; q.push((quality){nx,ny,dis[nx][ny]}); } } } } } ll solve(ll sx,ll sy) { ll ans=0; dijkstra(sx,sy); for(ll i=1;i<=3;i++) { for(ll j=1;j<=m;j++) { if(i==sx&&j==sy) continue; ans=(ans+dis[i][j]%p)%p; } } return ans; } int main() { #define Isaac #ifdef Isaac freopen("snowfinch.in","r",stdin); freopen("snowfinch.out","w",stdout); #endif ll ans=0,i,j; scanf("%lld",&m); for(i=1;i<=3;i++) { for(j=1;j<=m;j++) scanf("%lld",&a[i][j]); } for(i=1;i<=3;i++) { for(j=1;j<=m;j++) ans=(ans+solve(i,j))%p; } printf("%lld\n",ans); return 0; }
-
正解
- 先考虑怎么快速处理多源最短路。
- 设
表示仅考虑 中 和 的最短路,转移方程为 。 - 此时如果我们能够顺次(从右到左或从左到右)得到若干个点到某一个汇点的距离,则分讨三个转移而来的方向即可得到所在位置的最短路。
- 接着考虑分治。设当前分治区间为
,则统计出 的最短路 。 - 显然
之间的最短路形如 。由上面的转移容易得到左右两边每个点到 的最短路。 - 设
表示 到 的最短路, 表示 到 的最短路。则有 即为所求。 - 假设
被计入答案则有 ,移项分别得到 ,树状数组维护扫描线即可。具体地,将 看做修改,将 看做查询。 - 注意因最短路相等而导致的算重问题。
点击查看代码
const ll p=1000000007; ll a[4][200010],f[200010],g[200010],L[4][4][200010],R[4][4][200010],d[600010],n,ans=0; struct node { ll x,y,val,op; bool operator < (const node &another) const { return (x==another.x)?(op<another.op):(x<another.x); } }; vector<node>q; struct BIT { ll c[2][600010]; void clear() { for(ll i=1;i<=d[0];i++) c[0][i]=c[1][i]=0; } ll lowbit(ll x) { return (x&(-x)); } void add(ll n,ll x,ll val1,ll val2) { for(ll i=x;i<=n;i+=lowbit(i)) { c[0][i]=(c[0][i]+val1)%p; c[1][i]=(c[1][i]+val2)%p; } } ll getsum(ll x,ll val) { ll sum1=0,sum2=0; for(ll i=x;i>=1;i-=lowbit(i)) { sum1=(sum1+c[0][i])%p; sum2=(sum2+c[1][i])%p; } return (sum1+sum2*val%p)%p; } }T; void dp(ll l,ll r,ll mid) { L[1][1][mid]=a[1][mid]; L[1][2][mid]=a[1][mid]+a[2][mid]; L[1][3][mid]=min(f[mid],g[mid]); L[2][1][mid]=a[1][mid]+a[2][mid]; L[2][2][mid]=a[2][mid]; L[2][3][mid]=a[2][mid]+a[3][mid]; L[3][1][mid]=min(f[mid],g[mid]); L[3][2][mid]=a[2][mid]+a[3][mid]; L[3][3][mid]=a[3][mid]; for(ll op=1;op<=3;op++) { for(ll i=mid-1;i>=l;i--) { L[op][1][i]=min({L[op][1][i+1]+a[1][i],L[op][2][i+1]+a[2][i]+a[1][i],L[op][3][i+1]+f[i]}); // 从 (1,i) 到 (op,mid) L[op][3][i]=min({L[op][1][i+1]+f[i],L[op][2][i+1]+a[2][i]+a[3][i],L[op][3][i+1]+a[3][i]}); L[op][2][i]=min({L[op][1][i]+a[2][i],L[op][2][i+1]+a[2][i],L[op][3][i]+a[2][i]}); } } mid++; R[1][1][mid]=a[1][mid]; R[1][2][mid]=a[1][mid]+a[2][mid]; R[1][3][mid]=min(f[mid],g[mid]); R[2][1][mid]=a[1][mid]+a[2][mid]; R[2][2][mid]=a[2][mid]; R[2][3][mid]=a[2][mid]+a[3][mid]; R[3][1][mid]=min(f[mid],g[mid]); R[3][2][mid]=a[2][mid]+a[3][mid]; R[3][3][mid]=a[3][mid]; for(ll op=1;op<=3;op++) { for(ll i=mid+1;i<=r;i++) { R[op][1][i]=min({R[op][1][i-1]+a[1][i],R[op][2][i-1]+a[2][i]+a[1][i],R[op][3][i-1]+g[i]}); R[op][3][i]=min({R[op][1][i-1]+g[i],R[op][2][i-1]+a[2][i]+a[3][i],R[op][3][i-1]+a[3][i]}); R[op][2][i]=min({R[op][1][i]+a[2][i],R[op][2][i-1]+a[2][i],R[op][3][i]+a[2][i]}); } } } void work() { T.clear(); sort(q.begin(),q.end()); d[0]=0; for(ll i=0;i<q.size();i++) d[++d[0]]=q[i].y; sort(d+1,d+1+d[0]); d[0]=unique(d+1,d+1+d[0])-(d+1); for(ll i=0;i<q.size();i++) { q[i].y=lower_bound(d+1,d+1+d[0],q[i].y)-d; if(q[i].op==0) T.add(d[0],q[i].y,q[i].val%p,1); else ans=(ans+T.getsum(q[i].y,q[i].val%p))%p; } } void solve(ll l,ll r) { if(l==r) { ans=(ans+a[1][l]+2*a[2][l]+a[3][l]+min(f[l],g[l]))%p; return; } ll mid=(l+r)/2; solve(l,mid); solve(mid+1,r); dp(l,r,mid); for(ll z=1;z<=3;z++) { q.clear(); ll x=((z==1)?2:1),y=((z==3)?2:3); for(ll op=1;op<=3;op++) { for(ll i=l;i<=mid;i++) q.push_back((node){L[z][op][i]-L[x][op][i]+(z!=1),L[z][op][i]-L[y][op][i]+(z==3),L[z][op][i],0}); for(ll i=mid+1;i<=r;i++) q.push_back((node){R[x][op][i]-R[z][op][i],R[y][op][i]-R[z][op][i],R[z][op][i],1}); } work(); } } int main() { #define Isaac #ifdef Isaac freopen("snowfinch.in","r",stdin); freopen("snowfinch.out","w",stdout); #endif cin>>n; for(ll i=1;i<=3;i++) { for(ll j=1;j<=n;j++) cin>>a[i][j]; } f[0]=g[n+1]=0x3f3f3f3f3f3f3f3f; for(ll i=1;i<=n;i++) f[i]=min(f[i-1],a[2][i])+a[1][i]+a[3][i]; for(ll i=n;i>=1;i--) g[i]=min(g[i+1],a[2][i])+a[1][i]+a[3][i]; solve(1,n); cout<<ans*2%p<<endl; return 0; }
C. 燕鸥
-
正解
点击查看代码
ll calc(ll pos,ll n,ll l,ll r) { ll x=0,h=0; while((x+1)*3<=pos-1) x=(x+1)*3; x++; h=x; if(x!=pos) { h+=(2-(pos-x)%2)*pos+(x-pos)/2; x=pos; } while(x+1<=n&&h>=x+1) { x++; h-=x; } if((n-x)>h*2) { x+=h*2; h=0; while((x+1)*3<=n-1) x=(x+1)*3; x++; h=x; } h+=(n-x)%2*n-(n-x)/2; return l<=h&&h<=r; } ll solve(ll n,ll l,ll r) { ll ans=calc(n-1,n,l,r)+calc(n,n,l,r),x; for(ll i=1;i<=min(n-2,3ll);i++) ans+=calc(i,n,l,r); if(n>=4) { x=3; while((x+1)*3<n-1) { ans+=calc(x+3,n,l,r)*(((x+1)*3-x-2)/2-1); ans+=calc(x+1,n,l,r)*(((x+1)*3-x-1)/2+1); x=(x+1)*3; ans+=calc(x,n,l,r)+calc(x-2,n,l,r); } if((n-1-x)%2==1) { ans+=calc(x+3,n,l,r)*((n-1-x-2)/2-((x+1)*3-2<n-1)); ans+=calc(x+1,n,l,r)*((n-1-x-1)/2+1); if((x+1)*3-2<n-1) ans+=calc((x+1)*3-2,n,l,r); } else { ans+=calc(n-2,n,l,r); if(x+1!=n-2) { ans+=calc(x+3,n,l,r)*((n-2-x-2)/2-((x+1)*3-2<n-1)); ans+=calc(x+1,n,l,r)*((n-2-x-1)/2+1); if((x+1)*3-2<n-1) ans+=calc((x+1)*3-2,n,l,r); } } } return ans; } int main() { #define Isaac #ifdef Isaac freopen("tern.in","r",stdin); freopen("tern.out","w",stdout); #endif ll t,n,l,r,i; cin>>t; for(i=1;i<=t;i++) { cin>>n>>l>>r; cout<<solve(n,l,r)<<endl; } return 0; }
总结
因常数较大,挂了 。 忘开long long
和大量使用memset
挂了 。
后记
- 教练开场
才想起来放下发文件。 题面有点误导人了,读了 后才明白问的是什么。 题面中问的是具体方案,但只回答了方案数。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18701409,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探