spoj375 QTREE1 Query on a treeⅠ【树剖模版带一丢注释】
题目链接:http://www.spoj.com/problems/QTREE/en/
题目大意:两个操作:修改边权&查询路径中的最大值
=========================================================================
题解:裸的树剖..
然而第一次打的我,,交了7遍啊7遍>< [虽然现在看来没什么但是那个时候也是快疯了
树剖细节注意:
1、要利用两点间的路径干嘛干嘛往上跳时,注意y=fa[ty](因为ty到y间的路径已经处理完了下次处理的就是fa[ty]到x的了)
(经常无意识的打错,,虽然知道是ty然而一手快... 啊 ty=top[y]就是y在他所在重链的根
2、有翻转之类的标记,一定一定要记得下传。操作完后子树的值可能会改变的要记得更新。
3、最orz的树剖是搞边的,,用个ys[]记录该点与其父亲的边就好了。。。LCT才是搞点的遇到搞边的才要拆边成点等等等
(有一次搞混了orz打着打着忽然发现了什么不对的..
4、初始化...无论哪道题...一定要有意识QAQ 调过N遍了!!!
代码(算模版了吧)
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 50100 #define INF 0x7fffffff int dep[maxn],son[maxn],fa[maxn]; int tot[maxn],top[maxn];//tot[x]-x所在子树的结点个数 top[x]-x所在重链的起始端点 int ys[maxn],z=0;//ys[x]-x与它父亲的那条边的‘新’编号 //因为要让一条重链上的点的新编号连在一起好用线段树维护 所以要重新编号 struct node { int x,y,c,next; }a[maxn*2],e[maxn];int len,first[maxn]; struct tree { int l,r,lc,rc,mx; }tr[maxn*2];int tlen; int mymax(int x,int y){return (x>y)?x:y;} void ins(int x,int y,int c) { len++;a[len].c=c; a[len].x=x;a[len].y=y; a[len].next=first[x];first[x]=len; } void dfs1(int x) { tot[x]=1;son[x]=0; for (int k=first[x];k!=-1;k=a[k].next) { int y=a[k].y; if (y!=fa[x]) { dep[y]=dep[x]+1; fa[y]=x; dfs1(y); if (tot[son[x]]<tot[y]) son[x]=y; tot[x]+=tot[y]; } } } void dfs2(int x,int tp) { ys[x]=++z;top[x]=tp; if (son[x]!=0) dfs2(son[x],tp); for (int k=first[x];k!=-1;k=a[k].next) { int y=a[k].y; if (y!=fa[x] && y!=son[x]) dfs2(y,y); } } void bt(int l,int r) { tlen++;int now=tlen; tr[tlen].l=l;tr[tlen].r=r; tr[tlen].lc=tr[tlen].rc=-1; tr[tlen].mx=-INF; if (l<r) { int mid=(l+r)>>1; tr[now].lc=tlen+1;bt(l,mid); tr[now].rc=tlen+1;bt(mid+1,r); } } void change(int now,int x,int k) { if (tr[now].l==tr[now].r) {tr[now].mx=k;return;} int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc; if (x<=mid) change(lc,x,k); else change(rc,x,k); tr[now].mx=mymax(tr[lc].mx,tr[rc].mx); } int findmax(int now,int l,int r) { if (tr[now].l==l && tr[now].r==r) return tr[now].mx; int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc; if (r<=mid) return findmax(lc,l,r); else if (l>mid) return findmax(rc,l,r); else return mymax(findmax(lc,l,mid),findmax(rc,mid+1,r)); } int query(int x,int y) { int tx=top[x],ty=top[y],ans=0; while(tx!=ty) { if(dep[tx]>dep[ty] ) { int t=x;x=y;y=t; t=tx;tx=ty;ty=t;//!!! } ans=mymax(ans,findmax(1,ys[ty],ys[y])); y=fa[ty];ty=top[y]; } if(x==y) return ans; else { if(dep[x]>dep[y]){int t=x;x=y;y=t;} return mymax(ans,findmax(1,ys[son[x]],ys[y]) ); } } int main() { int T,n,i,u,v,d;char s[20]; scanf("%d",&T); while (T--) { scanf("%d",&n); len=0;memset(first,-1,sizeof(first)); for (i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&d); ins(u,v,d);ins(v,u,d); e[i].x=u;e[i].y=v;e[i].c=d; } dep[1]=0;fa[1]=0;dfs1(1); z=0;dfs2(1,1); tlen=0;bt(1,z); for (i=1;i<n;i++) { if (dep[e[i].x]>dep[e[i].y]) { int tt=e[i].x;e[i].x=e[i].y;e[i].y=tt; } change(1,ys[e[i].y],e[i].c); } while (1) { scanf("\n%s",s); if (s[0]=='D') break; scanf("%d%d",&u,&v); if (s[0]=='C') { change(1,ys[e[u].y],v); }else if (s[0]=='Q') { printf("%d\n",query(u,v)); } } } return 0; }