当前位置: 首页 > news >正文

sm2025 模拟赛11 (2025.10.5)

文章目录

  • T1 厚牛堡(easy,100%)
  • T2 旅行商(mid,80%)
  • T3 登山(hard-,5%)
  • T4 樱之艺术家

T1 厚牛堡(easy,100%)

link
思路
易知传播天数越大,所需奶牛越少。于是我们找到每个连续段最大的可能的传播天数取最小值,直接计算即可。当然要注意对在序列两端的段特别考虑。

T2 旅行商(mid,80%)

link
思路
首先考虑如何判 −1-11 ,就是那些不能到达环的点,拓扑找出度为 000 的点即可。
易知如果资产 ≥\ge 环上边的最大限制,那么就一定可以在这个环上不停地走。设 ansians_iansi 为从 iii 出发的答案。对于一条边 (u,v,r,p)(u,v,r,p)(u,v,r,p) ,会有 ansu=min(ansu,min(r,ansv−p))ans_u=min(ans_u,min(r,ans_v-p))ansu=min(ansu,min(r,ansvp)) ,但是由于不是 DAG ,转移会有后效性。但我们发现 ansuans_uansu 会有上限,即总 ≤\le 所在环上的最大的 rrr 。并且如果从点的角度会有后效性,但每条边只会贡献一次答案。于是建反图,考虑 rrr 从大到小枚举转移的边,即一开始假设带了 rrr 元出发,这样一定合法,转移完一条边就删去它,这样图就能为 DAG 了,可以拓扑解决。可以保证最终答案不仅合法还能最优。

反思
场上想到一种做法,但不保证正确性。
因为知道求 −1-11 的时候要判环,我们想到 SCC ,将 −1-11 的点踢掉。对剩下的图缩点,得到一个 DAG (树)。注意到叶子结点原来一定为环,所以这些点只能永远在这个环上走,所以可以用最短路求出这个环上的点的 ansansans 。然后往上转移。非叶子节点可以在环上走也可以往下走,所以同样可以先最短路求出只在环上不停走时的 ansansans
不过这样好像一直都消除不了环的影响,还是应该不断删边变成 DAG 然后拓扑做。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5;int idx,head[maxn];
struct EDGE{ int v,next,id; ll ct,w; }e[maxn];
void Insert(int u,int v,ll ct,ll w,int id){e[++idx]={v,head[u],id,ct,w};head[u]=idx;
}int out[maxn];
ll ans[maxn];
bool vis[maxn];
struct EDGE2{ int x,y,id; ll ct,w; }eg[maxn];
queue<int>q;
int main(){int n,m; cin>>n>>m;for(int i=1;i<=m;i++){cin>>eg[i].x>>eg[i].y>>eg[i].ct>>eg[i].w; eg[i].id=i;out[eg[i].x]++;Insert(eg[i].y,eg[i].x,eg[i].ct,eg[i].w,eg[i].id);}for(int i=1;i<=n;i++)ans[i]=1e9;for(int i=1;i<=n;i++)if(!out[i]) q.push(i);sort(eg+1,eg+m+1,[](EDGE2 a,EDGE2 b){ return a.ct>b.ct; });for(int i=1;i<=m;i++){while(!q.empty()){int x=q.front();q.pop();for(int i=head[x];i;i=e[i].next){if(vis[e[i].id]) continue;vis[e[i].id]=1;int v=e[i].v;out[v]--;if(!out[v]) q.push(v);if(ans[x]!=1e9) ans[v]=min(ans[v],max(e[i].ct,ans[x]-e[i].w));}}if(!vis[eg[i].id]){vis[eg[i].id]=1;out[eg[i].x]--;if(!out[eg[i].x]) q.push(eg[i].x);ans[eg[i].x]=min(ans[eg[i].x],eg[i].ct);}}for(int i=1;i<=n;i++)cout<<(ans[i]==1e9?-1:ans[i])<<" ";return 0;
}

T3 登山(hard-,5%)

link
orzsst
思路
设每座山初始高度为 aia_iai
首先考虑最终每座山有多高,有 hi=min(max⁡j=1iaj,max⁡j=inaj)h_i=min(\max\limits_{j=1}^{i} a_j,\max\limits_{j=i}^{n} a_j)hi=min(j=1maxiaj,j=imaxnaj)
即山峰一定为序列最大值,设位置为 xxx 。那么在 [1,x)[1,x)[1,x) 中找最大值,记下标为 pppi∈[p,x),hi=hpi \in [p,x),h_i=h_pi[p,x),hi=hp 。然后继续在 [1,p)[1,p)[1,p) 中找最大值,重复做即可。右边 (x,n](x,n](x,n] 同理。会发现只有这一种情况合法。
现在考虑如何将 aia_iai -> hih_ihi
首先我们肯定要在 [1,i)[1,i)[1,i)(i,n](i,n](i,n] 中分别找一个最小的比 aia_iai 大的数当作代价中的 h[i],h[k],这样肯定最优,但是这样 aia_iai 的变化会对取的数有不断影响,仍不好做。于是我们希望相同值的 iii 一起处理到下一个有意义的值,这样就避免了取的数会不断变化,但是我们还是不知道要怎么做。
继续发现性质,如果有 ai<aja_i \lt a_jai<aj ,那肯定是优先修改 aia_iai 直到 ai>aja_i \gt a_jai>aj
当有一堆数满足 ai=aja_i=a_jai=aj 时,设这堆数最小的位置为 lll ,最大位置为 rrr ,会想到先将 ala_lalara_rar+1+1+1 ,然后让中间的数分别 +1+1+1 ,这样一直更改到目标值肯定是最优的,具体 al,ara_l,a_ral,ar 二者 +1+1+1 的先后顺序比较一下就好。
那么就是先从小到大枚举 aia_iai 的值域 VVV(个数为 O(n)O(n)O(n)),每次将等于这个值的 aia_iai 加入 set 中,可知此时 set 中的所有数都等于这个值,那么就将 set 中的所有数变到 VVV 中的下一个值(这个代价推一下式子就好),如果 set 中的某些数已经达到最终高度 hih_ihi 了就扔出 set 。这样最终所有数都会达到相应的 hih_ihi
另外,如何在一段区间 [l,r][l,r][l,r] 中找到最小的大于 xxx 的数。可以考虑用线段树维护。在将 aia_iai 加入 set 的时候,就意味着 ai≤a_i\leai 当前的值,将 aia_iai 改为 INF 即可,那剩下的不是 INF 的数就都 >\gt> 当前值,查询就是查区间最小值。

代码

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
const ll INF=2e9,mod=1e6+3;int a[maxn];
struct TREE{ ll mi; }tree[maxn*4];
void Build(int rt,int l,int r){if(l==r){tree[rt].mi=a[l];return;}int mid=(l+r)>>1;Build(rt*2,l,mid); Build(rt*2+1,mid+1,r);tree[rt].mi=min(tree[rt*2].mi,tree[rt*2+1].mi);
}void Modify(int rt,int l,int r,int x,ll y){if(l==r){tree[rt].mi=y;return;}int mid=(l+r)>>1;if(x<=mid) Modify(rt*2,l,mid,x,y);else Modify(rt*2+1,mid+1,r,x,y);tree[rt].mi=min(tree[rt*2].mi,tree[rt*2+1].mi);
}ll Query(int rt,int l,int r,int x,int y){if(x>y) return INF;if(x<=l&&r<=y) return tree[rt].mi;int mid=(l+r)>>1; ll s=INF;if(x<=mid) s=min(s,Query(rt*2,l,mid,x,y));if(y>mid) s=min(s,Query(rt*2+1,mid+1,r,x,y));return s;
}int h[maxn];
ll a2[maxn];
set<int>st;
vector<int>vt[maxn],vt2[maxn];
int main(){freopen("hike.in","r",stdin);freopen("hike.out","w",stdout);int n; scanf("%d",&n); int ma=0;for(int i=1;i<=n;i++){scanf("%lld",&a[i]); a2[i]=a[i];//! if(a[ma]<a[i]) ma=i;} for(int i=1;i<=ma;i++)h[i]=max(h[i-1],a[i]);for(int i=n;i>ma;i--)h[i]=max(h[i+1],a[i]);sort(a2+1,a2+n+1);int m=unique(a2+1,a2+n+1)-a2-1;for(int i=1;i<=n;i++){int ph=lower_bound(a2+1,a2+m+1,a[i])-a2;int ph2=lower_bound(a2+1,a2+m+1,h[i])-a2;vt[ph].push_back(i);vt2[ph2].push_back(i);}Build(1,1,n);ll ans=0;for(int i=1;i<m;i++){for(auto j:vt[i]){st.insert(j);Modify(1,1,n,j,INF);}for(auto j:vt2[i])st.erase(j);if(st.empty()) continue;int l=*st.begin(),r=*st.rbegin();ll x=Query(1,1,n,1,l-1),y=Query(1,1,n,l+1,n),p=Query(1,1,n,1,r-1),q=Query(1,1,n,r+1,n);ll len=st.size(),s=a2[i+1]-a2[i];if(len==1) (ans+=(x+y)*s%mod)%=mod,(ans+=(a2[i]+a2[i+1]-1)*s/2%mod)%=mod;else{(ans+=(x+q+min(y,p))*s%mod)%=mod;(ans+=(a2[i]+1+a2[i+1])*s/2%mod*(2*len-3)%mod)%=mod;(ans+=(a2[i]+a2[i+1]-1)*s/2%mod*len%mod)%=mod;}}printf("%lld",ans);return 0;
}

T4 樱之艺术家

link
不会啊

http://www.dtcms.com/a/450005.html

相关文章:

  • python镜像源配置
  • 4.寻找两个正序数组的中位数-二分查找
  • 理解CC++异步IO编程:Epoll入门
  • wordpress房屋网站模板微信小程序
  • 阿里网站建设视频教程WordPress云媒体库
  • SpringCloud 入门 - Nacos 配置中心
  • Windows 下使用 Claude Code CLI 启动 Kimi
  • 网站推广的基本方式抖音特效开放平台官网
  • 湖南网站排名wordpress插件seo
  • WindowsKyLin:nginx安装与配置
  • 【剑斩OFFER】算法的暴力美学——最大连续1的个数 III
  • UNIX下C语言编程与实践32-UNIX 僵死进程:成因、危害与检测方法
  • 论坛开源网站源码首页优化排名
  • 网站建设策请seo的人帮做网站排名
  • 旅游网站后台html模板做网站的做app的
  • 网站备案回访问题效果好的网站制作
  • Unity 光源
  • 应急响应
  • 【2061】梯形面积
  • 电商网站seo优化目标分解wordpress域名授权
  • tex 写的论文如何统计字数
  • 【区块链学习笔记】16:以太坊中的交易树和收据树
  • 盟接之桥谈制造:格局、行动、心态与认知的创业修行
  • 深入理解 Spring Bean 后处理器:@Autowired 等注解的本质
  • 购物网站排名2017专业商业空间设计公司
  • UDP 的报文结构和注意事项
  • C56-字符串拷贝函数strcpy与strnpy
  • SAM、SECURITY、SYSTEM 和 NTDS.dit 的详细区别
  • 网站建网站建设企业北京网络教育
  • 通过super()正确初始化超类:Effective Python 第40条