bzoj 3083 遥远的国度
解法
一道简单的套路题,然而我的线段树只修改了左区间居然还有90分,数据真的水。
我们考虑当前查询的点x,如果他是root的祖先,那么我们查询的是整棵树去掉x在x到root路径上的第一个儿子的子树。
否则查询的还是x的子树。
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <cctype> #include <vector> #include <cassert> #define INF 2139062143 #define MAX 0x7ffffffffffffff #define del(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; template<typename T> inline void read(T&x) { x=0;T k=1;char c=getchar(); while(!isdigit(c)){if(c=='-')k=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k; } const int maxn=100000+15; int w[maxn],new_w[maxn],deep[maxn],fa[maxn],son[maxn],id[maxn],sz[maxn],top[maxn],dfs_n,root; vector<int> G[maxn]; void dfs1(int u,int f) { fa[u]=f;deep[u]=deep[f]+1;sz[u]=1; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(v==f) continue; dfs1(v,u); sz[u]+=sz[v]; if(!son[u]||sz[v]>sz[son[u]]) son[u]=v; } } void dfs2(int u,int topf) { top[u]=topf;id[u]=++dfs_n;new_w[id[u]]=w[u]; if(son[u]) dfs2(son[u],topf); for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(v==fa[u]||v==son[u]) continue; dfs2(v,v); } } #define lc (cur*2) #define rc (cur*2+1) #define mid ((l+r)>>1) struct node{ int minn,laz; node() { laz=-1; } }T[4*maxn]; inline void pushdown(int cur) { if(T[cur].laz==-1) return; T[lc].minn=T[cur].laz; T[rc].minn=T[cur].laz; T[lc].laz=T[cur].laz; T[rc].laz=T[cur].laz; T[cur].laz=-1; } inline void update(int cur) { T[cur].minn=min(T[lc].minn,T[rc].minn); } void build(int cur,int l,int r) { if(l==r) { T[cur].minn=new_w[l];return; } build(lc,l,mid); build(rc,mid+1,r); update(cur); } void change(int cur,int l,int r,int ql,int qr,int k) { if(ql<=l&&r<=qr) {T[cur].minn=T[cur].laz=k;return;} if(l==r) return; pushdown(cur); if(ql<=mid) change(lc,l,mid,ql,qr,k); if(qr>mid) change(rc,mid+1,r,ql,qr,k);//不要多打else update(cur); } int query(int cur,int l,int r,int ql,int qr) { if(ql>qr) return INF; if(ql<=l&&r<=qr) return T[cur].minn; pushdown(cur); if(qr<=mid) return query(lc,l,mid,ql,qr); else if(ql>mid) return query(rc,mid+1,r,ql,qr); return min(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr)); } int n,m; inline void change(int x,int y,int k) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); change(1,1,n,id[top[x]],id[x],k); x=fa[top[x]]; } if(deep[x]<deep[y]) swap(x,y); change(1,1,n,id[y],id[x],k); return; } int get_son(int f,int s) { while(top[s]!=top[f]) { if(fa[top[s]]==f) return top[s]; s=fa[top[s]]; } return son[f]; } int main() { read(n),read(m); for(int i=1,x,y;i<n;i++) { read(x),read(y); G[x].push_back(y); G[y].push_back(x); } for(int i=1;i<=n;i++) read(w[i]); read(root); dfs1(root,0);dfs2(root,root); build(1,1,n); int opt; while(m--) { read(opt); if(opt==1) read(root); if(opt==2) { int x,y,w; read(x),read(y),read(w); change(x,y,w); } if(opt==3) { int x;read(x); if(x==root) {printf("%d\n",query(1,1,n,1,n));continue;} if(id[root]>id[x]&&id[root]<=id[x]+sz[x]-1) { int d=get_son(x,root); printf("%d\n",min(query(1,1,n,1,id[d]-1),query(1,1,n,id[d]+sz[d],n))); } else printf("%d\n",query(1,1,n,id[x],id[x]+sz[x]-1)); } } return 0; }