SPOJ - QTREE Query on a tree(树链剖分+线段树)
生活随笔
收集整理的這篇文章主要介紹了
SPOJ - QTREE Query on a tree(树链剖分+线段树)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一棵由n個點組成的樹,再給出數(shù)個操作,每次操作分為下列幾種類型:
題目分析:做做板子題練練代碼熟練度吧,起碼模板能夠熟練默寫后,再寫樹鏈剖分的函數(shù)就不太會犯低級錯誤了
回到這個題目上,因為是查詢點x-點y這條路徑上的最值,不難想到要用線段樹維護一下最大值,想要用線段樹的前提就是要有連續(xù)區(qū)間,我們用樹鏈剖分將整棵樹先剖一下,然后剩下的就是基本操作了
這個題目還是注意一下映射的關系,我都習慣在注釋中提前寫明白,不然自己在寫代碼的時候也會一不小心犯糊涂
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e4+100;int n;struct Node {int to,w,id;Node(int TO,int W,int ID){to=TO;w=W;id=ID;} };vector<Node>node[N];int fa[N],deep[N],son[N],num[N],val[N],rk[N];//val[節(jié)點]=權值 rk[編號]=節(jié)點 void dfs1(int u,int f,int dep) {son[u]=-1;deep[u]=dep;num[u]=1;fa[u]=f;for(auto i:node[u]){int v=i.to;int w=i.w;int id=i.id;if(v==f)continue;dfs1(v,u,dep+1);val[v]=w;rk[id]=v;num[u]+=num[v];if(son[u]==-1||num[son[u]]<num[v])son[u]=v;} }int top[N],id[N],idd[N],cnt;//id[節(jié)點]=編號 idd[編號]=節(jié)點 void dfs2(int u,int f,int root) {top[u]=root;id[u]=++cnt;idd[cnt]=u;if(son[u]!=-1)dfs2(son[u],u,root);for(auto i:node[u]){int v=i.to;if(v==f||v==son[u])continue;dfs2(v,u,v);} }struct tree {int l,r,mmax; }tree[N<<2];void pushup(int k) {tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax); } void build(int k,int l,int r) {tree[k].l=l;tree[k].r=r;if(l==r){tree[k].mmax=val[idd[l]];return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k); }void update(int k,int pos,int val) {if(tree[k].l==tree[k].r){tree[k].mmax=val;return;}int mid=tree[k].l+tree[k].r>>1;if(mid>=pos)update(k<<1,pos,val);elseupdate(k<<1|1,pos,val);pushup(k); }int query(int k,int l,int r) {if(tree[k].r<l||tree[k].l>r)return -inf;if(tree[k].l>=l&&tree[k].r<=r)return tree[k].mmax;return max(query(k<<1,l,r),query(k<<1|1,l,r)); }int solve(int u,int v) {int ans=-inf;while(top[u]!=top[v]){if(deep[top[u]]<deep[top[v]])swap(u,v);ans=max(ans,query(1,id[top[u]],id[u]));u=fa[top[u]];}if(u==v)return ans;if(deep[u]<deep[v])swap(u,v);ans=max(ans,query(1,id[v]+1,id[u]));return ans; } void init() {for(int i=1;i<=n;i++)node[i].clear();cnt=0; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%d",&n);init();for(int i=1;i<n;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);node[a].push_back(Node(b,c,i));node[b].push_back(Node(a,c,i));}dfs1(1,0,0);dfs2(1,0,1);build(1,1,n);char s[10];while(scanf("%s",s)!=EOF&&s[0]!='D'){if(s[0]=='C'){int x,y;scanf("%d%d",&x,&y);update(1,id[rk[x]],y);}else{int x,y;scanf("%d%d",&x,&y);printf("%d\n",solve(x,y));}}}return 0; }?
總結
以上是生活随笔為你收集整理的SPOJ - QTREE Query on a tree(树链剖分+线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 洛谷P5357 - 【模板】AC自动机(
- 下一篇: HDU - 1150 Machine S