2 条题解
-
0
本题是 USACO25OPEN 银组实现难度略大的题,由于这只属于银组知识范围,所以在此我当然不会用什么高级数据结构或算法,仅仅是一个朴素的的预处理即可。
根据题意,本题等效于给定一棵树和 个查询,求满足指定条件的到根结点路径的最大边权和。由于本题询问量比较大,我们有两个方向:一个是带 查询,还有一个是预处理。注意到本题 ,这透露给我们信息:可以预处理这 种勇气值情况,再由二分技能水平找到符合条件的最大乐趣值。
接下来考虑具体代码实现。我们可以由终点倒推,维护到每个出发点的前 大的难度值和总乐趣值。接下来,对于每种勇气值,我们分别对这些该勇气值加 大的难度值及乐趣值构成的结构体进行排序。(该勇气值加 大的难度值为临界情况,依此排序)接下来我们再遍历排序后的结构体数组,维护 上的乐趣最大值。接下来,对于每个查询,我们先对勇气值对号入座,再二分在排序后结构体数组中的定位,输出预处理出来的乐趣最大值即可。
时间复杂度 (,表示 值域大小)。
代码:
#include<bits/stdc++.h> using namespace std; int n,p[100010],k;//一次性 long long e[100010],d[100010],_max[12][100010],ans[12][100010]; struct Node{ long long e,max_[12]; bool operator<(const Node& x) {return max_[k]<x.max_[k]; } }a[100010]; long long max_[12][100010]; int main() {cin>>n; for(int i=2;i<=n;i++) {cin>>p[i]>>d[i]>>e[i]; e[i]+=e[p[i]]; a[i].e=e[i]; for(int j=1;j<=11;j++) _max[j][i]=_max[j][p[i]]; for(int j=1;j<=11;j++) {if(d[i]>_max[j][i]) swap(d[i],_max[j][i]); a[i].max_[j]=_max[j][i]; } } for(k=1;k<=11;k++) {sort(a+1,a+1+n); for(int i=2;i<=n;i++) {ans[k][i]=max(ans[k][i-1],a[i].e); max_[k][i]=a[i].max_[k]; } } int m;cin>>m; while(m--) {int s,c; cin>>s>>c; c++; int id=upper_bound(max_[c]+1,max_[c]+n+1,s)-max_[c]-1; cout<<ans[c][id]<<'\n'; } } -
0
#include<bits/stdc++.h> using namespace std; #define int long long const int N=1e5+10; int fa[N],d[N],e[N],ans[N],mx[15][N],f[15][N],nw; struct node{int id,f[15],siz;node(){memset(f,-1,sizeof(f));}}a[N]; bool cmp(node n1,node n2){return n1.f[nw]<n2.f[nw];} struct qnode{int c,s;}q[N]; signed main() { int n;cin>>n; for(int i=2;i<=n;i++)cin>>fa[i]>>d[i]>>e[i]; for(int i=1;i<=n;i++)a[i].id=i; for(int i=0;i<=10;i++)a[1].f[i]=0; for(int i=2;i<=n;i++) { a[i].siz=a[fa[i]].siz+e[i]; for(int j=10;j>=0;j--) { if(a[fa[i]].f[j]<d[i])a[i].f[j+1]=a[fa[i]].f[j]; else a[i].f[j]=a[fa[i]].f[j]; } for(int j=0;j<=10;j++)if(a[i].f[j]==-1&&a[fa[i]].f[j]!=-1)a[i].f[j]=d[i]; } for(int i=0;i<=10;i++) { nw=i;sort(a+1,a+n+1,cmp); for(int j=1;j<=n;j++)f[i][j]=a[j].f[i]; for(int j=1;j<=n;j++)mx[i][j]=max(mx[i][j-1],a[j].siz); } int m;cin>>m; for(int i=1;i<=m;i++) { int x,y;cin>>x>>y; int ans=upper_bound(f[y]+1,f[y]+n+1,x)-f[y]-1; cout<<mx[y][ans]<<'\n'; } return 0; }
- 1
信息
- ID
- 1564
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 34
- 已通过
- 16
- 上传者