spoj Query on a tree(树链剖分)

xiaoxiao2021-02-28  7

传送门 题解:树链剖分边权问题,属于本人万年不想碰系列,以前做过不少剖点权的,今天来填填坑。其实两种问题唯一不同的就是:边权问题需要把边权下放到儿子作为点权,然后在链剖向上跳的最后一步稍作修改即可。关于记录一条边以及它对应权值下放的点,本蒟蒻想了一个办法就是用map < pair < int ,int> ,int >,其中pair记录一条边起点终点,最后一个int即这条边权值下放的点编号。

经过肉眼在submission记录中的比较,这种写法略微牺牲时间但是代码长度较短。应该有更快的方法,不过对于链剖这种O(n*logn^2)的算法,在main()的外层循环加一个logn也几乎可以忽略不计(更何况map可是用红黑树实现的,快得吓人orzorz)

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<map> using namespace std; #define root 1,1,n #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define pii pair<int ,int > const int MAXN=10004,INF=0x3f3f3f3f; int n; int head[MAXN],edge,fa[MAXN],dep[MAXN],son[MAXN],siz[MAXN]; int top[MAXN],tid[MAXN],rk[MAXN],num[MAXN],tim; map<pii ,int > mp; struct EDGE { int u,v,nxt,w; }e[MAXN<<1]; char ss[5]; inline int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } inline void adde(int u,int v,int w) { e[++edge].nxt=head[u],e[edge].u=u,e[edge].v=v,e[edge].w=w,head[u]=edge; e[++edge].nxt=head[v],e[edge].u=v,e[edge].v=u,e[edge].w=w,head[v]=edge; } /*------------DCP------------*/ void dfs1(int p,int father,int d) { dep[p]=d,fa[p]=father,siz[p]=1; for (int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if (v^father) { mp[make_pair(e[i].u,e[i].v)]=v; mp[make_pair(e[i].v,e[i].u)]=v; dep[v]=dep[p]+1; num[v]=e[i].w; dfs1(v,p,d+1); siz[p]+=siz[v]; if (son[p]==-1||siz[son[p]]<siz[v]) son[p]=v; } } } void dfs2(int p,int tp) { top[p]=tp,tid[p]=++tim,rk[tim]=p; if (son[p]==-1) return ; dfs2(son[p],tp); for (int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if (v^fa[p]&&v^son[p]) dfs2(v,v); } } /*------------SegTree------------*/ int mx[MAXN<<2]; inline void pushup(int rt) { mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); } void build(int rt,int l,int r) { if (l==r) {mx[rt]=num[rk[l]];return ;} int mid=(l+r)>>1; build(lson); build(rson); pushup(rt); } void modify(int rt,int l,int r,int pos,int val) { if (l==r) {mx[rt]=val;return ;} int mid=(l+r)>>1; if (pos<=mid) modify(lson,pos,val); else modify(rson,pos,val); pushup(rt); } int query(int rt,int l,int r,int L,int R) { if (L<=l&&r<=R) return mx[rt]; int mid=(l+r)>>1,ret=-INF; if (L<=mid) ret=max(ret,query(lson,L,R)); if (mid<R) ret=max(ret,query(rson,L,R)); return ret; } int ask(int x,int y) { int ret=-INF; while (top[x]^top[y]) { if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y; ret=max(ret,query(root,tid[top[x]],tid[x])); x=fa[top[x]]; } if (x==y) return ret; if (dep[x]>dep[y]) x^=y^=x^=y; ret=max(ret,query(root,tid[son[x]],tid[y]));//son!!! return ret; } int main() { // freopen("spoj qot.in","r",stdin); int kase=read(); while (kase--) { edge=tim=0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); n=read(); for (int i=1;i<n;++i) { int u=read(),v=read(),w=read(); adde(u,v,w); } dfs1(1,0,0); num[1]=-INF,dfs2(1,1); build(root); while (scanf("%s",ss)&&ss[1]^'O') { if (ss[0]=='Q') { int x=read(),y=read(); printf("%d\n",ask(x,y)); } else { int eg=read()<<1,val=read(); int u=e[eg].u,v=e[eg].v; int pos=mp[make_pair(u,v)]; modify(root,tid[pos],val); } } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-450341.html

最新回复(0)