日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

SPOJ - QTREE Query on a tree(树链剖分+线段树)

發布時間:2024/4/11 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SPOJ - QTREE Query on a tree(树链剖分+线段树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一棵由n個點組成的樹,再給出數個操作,每次操作分為下列幾種類型:

  • QUERY x y:詢問點x-點y這條路徑上的所有邊權的最大值
  • CHANGE x y:將第x條邊的權值改為y
  • DONE:退出操作
  • 題目分析:做做板子題練練代碼熟練度吧,起碼模板能夠熟練默寫后,再寫樹鏈剖分的函數就不太會犯低級錯誤了

    回到這個題目上,因為是查詢點x-點y這條路徑上的最值,不難想到要用線段樹維護一下最大值,想要用線段樹的前提就是要有連續區間,我們用樹鏈剖分將整棵樹先剖一下,然后剩下的就是基本操作了

    這個題目還是注意一下映射的關系,我都習慣在注釋中提前寫明白,不然自己在寫代碼的時候也會一不小心犯糊涂

    代碼:

    #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[節點]=權值 rk[編號]=節點 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[節點]=編號 idd[編號]=節點 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(树链剖分+线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。