当前位置: 代码迷 >> 综合 >> CodeForces 893F Subtree Minimum Query (主席树+BFS|DFS)
  详细解决方案

CodeForces 893F Subtree Minimum Query (主席树+BFS|DFS)

热度:76   发布时间:2023-11-15 11:54:25.0

题目链接:http://codeforces.com/problemset/problem/893/F

题目大意

给定一棵树和根,每个节点上
都有权值,先给定若干个查询(强制在线,要求在题目中)
(x,k),问x节点的子树中其距离x不超过k的节点权值的最小值,
其中x自己规定距离为0.

题目分析 

思维蛮巧妙的主席树了,,
我也是参照了别人的思路才恍然大悟,
在数据结构的灵活使用方面还远远不够。。。
主席树本质上就是时间影响的叠加,所以关键是维护的前缀性质和时间序。
考虑对什么建立时间序,在题目中,其实把dp式子列一下就发现,
其影响是随深度变化而转转移的,那么我们试着以深度为时间序,
这里我们要把它映射成单值,详见代码,那么我们往这个时间序里丢的就是
节点数值了,但是什么又是节点的下标呢?以什么建立系来体现
时间关系呢?这里DFS序又被灵活用起来了,,太巧妙了。。。
不难发现我们对于深度d的树,假设我们一直以dfs序的左值建坐标丢值,
那么我们在深度d的树中可以通过节点x的DFS序来查询到,在这个深度之前的
在序区间中的所有点,这样就符合题目建模要求了。

#include<bits/stdc++.h>
using namespace std;#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=2e5+5;
const int inf=1e9+7;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定一棵树和根,每个节点上
都有权值,先给定若干个查询(强制在线,要求在题目中)
(x,k),问x节点的子树中其距离x不超过k的节点权值的最小值,
其中x自己规定距离为0.题目分析:
思维蛮巧妙的主席树了,,
我也是参照了别人的思路才恍然大悟,
在数据结构的灵活使用方面还远远不够。。。
主席树本质上就是时间影响的叠加,所以关键是维护的前缀性质和时间序。
考虑对什么建立时间序,在题目中,其实把dp式子列一下就发现,
其影响是随深度变化而转转移的,那么我们试着以深度为时间序,
这里我们要把它映射成单值,详见代码,那么我们往这个时间序里丢的就是
节点数值了,但是什么又是节点的下标呢?以什么建立系来体现
时间关系呢?这里DFS序又被灵活用起来了,,太巧妙了。。。
不难发现我们对于深度d的树,假设我们一直以dfs序的左值建坐标丢值,
那么我们在深度d的树中可以通过节点x的DFS序来查询到,在这个深度之前的
在序区间中的所有点,这样就符合题目建模要求了。
*/
int n,r,m,x,y,maxv,last;
int a[maxn],v[maxn];
int pl[maxn],pr[maxn],dep[maxn];///DFS序
vector<int> g[maxn];
int rt[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20],tot=0;
void build(int& o,int l,int r){o=++tot;sum[o]=inf;if(l==r) return;int mid=l+r>>1;build(ls[o],l,mid);build(rs[o],mid+1,r);
}
void update(int& o,int last,int l,int r,int p,int v){o=++tot;ls[o]=ls[last],rs[o]=rs[last];if(l==r) {sum[o]=v;return;}int mid=l+r>>1;if(p<=mid) update(ls[o],ls[o],l,mid,p,v);else update(rs[o],rs[o],mid+1,r,p,v);sum[o]=min(sum[ls[o]],sum[rs[o]]);return ;
}
int query(int o,int l,int r,int L,int R){if(L<=l&&r<=R) return sum[o];int mid=l+r>>1,ans=inf;if(L<=mid) ans=min(ans,query(ls[o],l,mid,L,R));if(mid<R) ans=min(ans,query(rs[o],mid+1,r,L,R));return ans;
}
///深搜
void dfs(int u,int pre){pl[u]=++tot;dep[u]=dep[pre]+1;maxv=max(maxv,dep[u]);for(int i=0;i<g[u].size();i++){int v=g[u][i];if(v==pre) continue;dfs(v,u);}pr[u]=tot;
}
///广搜
int vis[maxn],mp[maxn];
void bfs(){int tmp=0;queue<int> p;p.push(r);while(!p.empty()){int tp=p.front();p.pop();if(vis[tp]) continue;else vis[tp]=1;update(rt[tmp+1],rt[tmp],1,2*n,pl[tp],a[tp]);mp[dep[tp]]=++tmp;for(int i=0;i<g[tp].size();i++){if(vis[g[tp][i]]) continue;p.push(g[tp][i]);}}
}int main(){ios::sync_with_stdio(false);cin>>n>>r;rep(i,1,n+1) cin>>a[i];rep(i,1,n){cin>>x>>y;g[x].push_back(y);g[y].push_back(x);}dfs(r,0);tot=0;build(rt[0],1,n<<1);bfs();cin>>m;rep(i,0,m){cin>>x>>y;x=(x+last)%n+1,y=(y+last)%n;///cout<<min(dep[x]+y,maxv)<<endl;last=query(rt[mp[min(dep[x]+y,maxv)]],1,n<<1,pl[x],pr[x]);cout<<last<<'\n';}return 0;
}

 

  相关解决方案