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

10.22 NOTE

P9352 [JOI 2023 Final] 训猫 / Cat Exercise

题目传送门

思路

要求猫移动次数的最大值,显然,当只留了一条路时, 猫的移动方向是固定的,也就是说,我们可以决定这只猫走的方向,而这是一个树形结构,显然可以树形 DP。

但是要注意:
题目有一个条件是,只能走向次高点,也就是说,我们必须根据权值从小到大来 DP,那么通常的建图方法是不适用的,正确性直接没了,但是观察到结点的权值是 1~n 中的所有数,且不重复,所以可以考虑根据每个结点的权值建边,通过并查集维护已经处理过的连通块的权值最大点,通过枚举 \(1\)\(n\) 实现转移,一定是正确的。

总结

并查集

当题目中有图上动态连通性的问题需要维护一个集合的代表等问题时,考虑使用并查集。

关于转换题目

当熟悉的建图方法在一些题中会丢失正确性且根据其他方式建图时能够保证正确性时,可以考虑一下。

一定要注意查看数据范围

Code

#include<bits/stdc++.h>
#define Iseri namespace
#define Nina std
#define Kawaragi int
#define Momoka main
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define ll long long
#define ull unsigned long long
#define endl "\n"
#define pii pair<ll,ll>
const int maxn=1000005;
const int inf=0x3f3f3f3f;using Iseri Nina;inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}return x*f;
}//===========================================================ll n,p[maxn],x,y,f[maxn],fa[maxn][20],lg[maxn],dep[maxn],dp[maxn];
vector<ll>v[maxn];inline ll find(ll x){if(x==f[x])return x;else return f[x]=find(f[x]);
}inline void dfs(ll u,ll lst){fa[u][0]=lst;dep[u]=dep[lst]+1;for(ll i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];for(auto i:v[u]){if(i==lst)continue;dfs(i,u);}return;
}inline ll lca(ll a,ll b){if(dep[a]<dep[b])swap(a,b);while(dep[a]>dep[b])a=fa[a][lg[dep[a]-dep[b]]-1];if(a==b)return a;for(ll i=lg[dep[a]];i>=0;i--)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];return fa[a][0];
}inline ll dis(ll a,ll b){return dep[a]+dep[b]-(2*dep[lca(a,b)]);}Kawaragi Momoka(){n=read();for(ll i=1;i<=n;i++){p[i]=read();f[i]=i;lg[i]=lg[i-1]+(1<<lg[i-1]==i);}for(ll i=1;i<n;i++){x=read(),y=read();v[p[x]].push_back(p[y]);v[p[y]].push_back(p[x]);}dfs(1,0);for(ll u=1;u<=n;u++){for(auto i:v[u]){ll t=find(i);if(t<u)f[t]=u,dp[u]=max(dp[u],dp[t]+dis(u,t));}}printf("%lld",dp[n]);return 0;
}

P2403 [SDOI2010] 所驼门王的宝藏

思路

挺简单的。通过观察就可以知道这是一个在 DAG 上 DP 的题目,然而其中可能有环,所以我们可以先 Tarjan 缩点缩成一个 DAG 之后再 DP 即可。

难点主要在如何建图。由于结点数太多,所以我们可以建一个特殊点代表每一行/每一列的点,建图时朝着这个特殊点连边即可,特殊点的点权设为0就不会影响正确性了。

这个很难想,需要细思,但是想到后会觉得很妙。

总结

建图方法

对于结点数很多,而且点之间有特殊约束(比如在网格图上在同一行/同一列)时,考虑建特殊点建图。

Code

#include<bits/stdc++.h>
#define Iseri namespace
#define Nina std
#define Kawaragi int
#define Momoka main
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define ll long long
#define ull unsigned long long
#define endl "\n"
#define pii pair<ll,ll>
const int maxn=2100005;
const int inf=0x3f3f3f3f;using Iseri Nina;inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}return x*f;
}//===========================================================struct node{int x,y,z;
}a[maxn];int n,r,c,def[maxn],w[maxn],f[maxn],dfn[maxn],low[maxn],inst[maxn],t,cnt,rd[maxn];
vector<int>e[maxn],v[maxn];
stack<int>s;
int dx[8]={1,1,0,-1,-1,-1,0,1};
int dy[8]={0,-1,-1,-1,0,1,1,1};inline bool cmp(node a,node b){return (a.x!=b.x)?a.x<b.x:a.y<b.y;}inline int get(node u){int l=1,r=n;while(l<=r){int mid=(l+r)>>1;if(a[mid].x==u.x&&a[mid].y==u.y)return mid;else if(a[mid].x<u.x||a[mid].x==u.x&&a[mid].y<u.y)l=mid+1;else r=mid-1;}return -1;
}inline void tarjan(int u){dfn[u]=low[u]=++t;s.push(u);inst[u]=1;for(auto i:e[u]){if(dfn[i]==0){tarjan(i);low[u]=min(low[u],low[i]);}else{if(inst[i])low[u]=min(low[u],dfn[i]);}}if(dfn[u]==low[u]){cnt++;while(s.top()!=u){int tmp=s.top();s.pop();inst[tmp]=0;def[tmp]=cnt;w[cnt]+=(tmp>r+c)?1:0;}def[u]=cnt;w[cnt]+=(u>r+c)?1:0;s.pop();inst[u]=0;}return;
}Kawaragi Momoka(){n=read(),r=read(),c=read();for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read(),a[i].z=read();sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++){e[a[i].x].push_back(r+c+i);e[a[i].y+r].push_back(r+c+i);if(a[i].z==1)e[r+c+i].push_back(a[i].x);else if(a[i].z==2)e[r+c+i].push_back(a[i].y+r);else{for(int j=0;j<=7;j++){node tmp;tmp.x=a[i].x+dx[j];tmp.y=a[i].y+dy[j];if(tmp.x>=1&&tmp.x<=r&&tmp.y>=1&&tmp.y<=c){int res=get(tmp);if(res!=-1)e[r+c+i].push_back(r+c+res);} }}}int top=r+c+n;for(int i=1;i<=top;i++)if(!dfn[i])tarjan(i);for(int i=1;i<=top;i++){for(auto j:e[i]){if(def[j]!=def[i])v[def[i]].push_back(def[j]),rd[def[j]]++;}}queue<int>q;for(int i=1;i<=cnt;i++)if(rd[i]==0)q.push(i),f[i]=w[i];while(!q.empty()){int u=q.front();q.pop();for(auto i:v[u]){f[i]=max(f[i],f[u]+w[i]);if(--rd[i]==0)q.push(i);}}int ans=0;for(int i=1;i<=cnt;i++)ans=max(ans,f[i]);printf("%d",ans);return 0;
}

十年 OI 一场空,开了 \(long\) \(long\) 见祖宗!!!

http://www.jsqmd.com/news/39774/

相关文章:

  • 题解:CF2106D Flower Boy
  • 使用 Maven 内置的版本号(Version)统一控制功能
  • 使用 Maven 内置的版本号(Version)统一控制功能
  • 2025年智能仓储服务商综合实力TOP5榜单:引领物流效率革命,覆盖山东、河北、江浙沪等国内线路,服务中亚五国、俄罗斯、阿富汗等国际路线
  • 2025年共享仓库服务最新TOP5推荐:山东、河北、江浙沪等国内区域,中亚、阿富汗、俄罗斯等国际地区,高效仓储解决方案引领者
  • 在ec2上部署CosyVoice2模型
  • 2025年配送中心最新综合实力TOP5榜单:引领国内国际物流新标杆
  • 每日反思(2025_11_13)
  • 2025年运输服务企业最新TOP5评测:国内、跨境物流解决方案引领者
  • 前后端全栈技术栈深度剖析:从Vue到Node.js的完整学习路径
  • 11月113日日记
  • 2025国内供应链服务企业最新TOP5评测:稳定、成本可控、合作灵活
  • 2025物流企业最新TOP5:覆盖范围广、团队更专业,成就时效与诚信
  • 疲劳数据分析与设计曲线 25
  • 11-13午夜盘思
  • 【AI翻译】分布式系统中的心跳机制
  • “ArcGIS Pro制图-模型构建器-ArcPy开发-AI-无人机实操”系列培训班预告
  • 送女生礼物推荐:如何才能送到心坎里?
  • 代码随想录Day9_字符串2
  • 2025年西北地区新媒体运营公司最新TOP5评测:AI赋能陕西甘肃品牌增长新引擎
  • 20251113日报
  • 控制领域常用希腊字母表
  • Windows 修改hosts不生效
  • 早就下好了IEDA,也算是差生文具多了
  • Pyinstaller - Python桌面应用打包的首选工具 - 详解
  • DNS record types: AAAA vs AA All In One
  • 关于Langchain更新解决Memory的引用
  • win7 打开 icmp-ping 回显
  • 旋转矩阵在导航与机器人中的应用
  • JVM之锁优化(自旋锁 适应性自旋 锁消除 锁粗化 轻量级锁 偏向锁) - 教程