QTREEⅠ SPOJ

树剖模板,注意把边化为点后要查到y的儿子。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=25000;
  4 int f[N],bel[N],w[N],id[N],pos[N],d[N],size[N],son[N],head[N];
  5 int n,idx,cnt,num,T,rt;
  6 struct node
  7 {
  8     int l,r,s,mx;
  9     void clean()
 10     {
 11         l=r=s=mx=-1e9;
 12     }
 13 }t[N<<2];
 14 struct edge
 15 {
 16     int to,nex,w,x;
 17 }e[N<<1],a[N];
 18 void add(int x,int y,int w)
 19 {
 20     e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].x=x;
 21 }
 22 void dfs1(int x,int fa)
 23 {
 24     size[x]=1;
 25     for(int i=head[x];i;i=e[i].nex)
 26     {
 27         int y=e[i].to;
 28         if(y==fa)continue;
 29         f[y]=x;d[y]=d[x]+1;
 30         dfs1(y,x);
 31         if(size[y]>size[son[x]])son[x]=y;
 32         size[x]+=size[y];
 33     }
 34     return;
 35 }
 36 void dfs2(int x,int chain)
 37 {
 38     bel[x]=chain;pos[x]=++idx;id[idx]=x;
 39     if(son[x])dfs2(son[x],chain);
 40     for(int i=head[x];i;i=e[i].nex)
 41     {
 42         int y=e[i].to;
 43         if(y==f[x]||y==son[x])continue;
 44         dfs2(y,y);
 45     }
 46 }
 47 void build(int &x,int l,int r)
 48 {
 49     x=++num;
 50     if(l==r){
 51         t[x].s=t[x].mx=w[l];return;
 52     }
 53     int mid=l+r>>1;
 54     build(t[x].l,l,mid);build(t[x].r,mid+1,r);
 55     t[x].mx=max(t[t[x].l].mx,t[t[x].r].mx);
 56     return; 
 57 }
 58 int query(int x,int l,int r,int L,int R)
 59 {
 60     if(l==L&&r==R)return t[x].mx;
 61     int mid=l+r>>1;
 62     if(R<=mid)return query(t[x].l,l,mid,L,R);
 63     else if(L>mid)return query(t[x].r,mid+1,r,L,R);
 64     else return max(query(t[x].l,l,mid,L,mid),query(t[x].r,mid+1,r,mid+1,R)); 
 65 }
 66 void change(int x,int l,int r,int pos,int ww)
 67 {
 68     if(l==r){t[x].s=t[x].mx=ww;return;}
 69     int mid=l+r>>1;
 70     if(pos<=mid)change(t[x].l,l,mid,pos,ww);
 71     else change(t[x].r,mid+1,r,pos,ww);
 72     t[x].mx=max(t[t[x].l].mx,t[t[x].r].mx);
 73 }
 74 int querytree(int x,int y)
 75 {
 76     int ans=-1e9;
 77     while(bel[x]!=bel[y])
 78     {
 79         if(d[bel[x]]<d[bel[y]])swap(x,y);
 80         ans=max(ans,query(rt,1,n,pos[bel[x]],pos[x]));
 81         x=f[bel[x]];
 82     }
 83     if(d[x]<d[y])swap(x,y);
 84     if(d[son[y]]<=d[x])
 85     ans=max(ans,query(rt,1,n,pos[son[y]],pos[x]));
 86     return ans;
 87 }
 88 void init()
 89 {
 90     memset(f,0,sizeof(f));
 91     memset(d,0,sizeof(d));
 92     memset(size,0,sizeof(size));
 93     memset(son,0,sizeof(son));
 94     memset(bel,0,sizeof(bel));
 95     memset(pos,0,sizeof(pos));
 96     memset(head,0,sizeof(head));
 97     memset(id,0,sizeof(id));
 98     memset(w,0,sizeof(w));cnt=idx=num=0;rt=0;
 99     for(int i=1;i<=num;++i)t[i].clean();
100 }
101 int main()
102 {
103     scanf("%d",&T);
104     while(T--)
105     {
106         init();int x,y,ww;
107         scanf("%d",&n);
108         for(int i=1;i<n;++i)
109         {
110             scanf("%d%d%d",&x,&y,&ww);
111             add(x,y,ww);add(y,x,ww);
112             a[i].x=x;a[i].to=y;a[i].w=ww;
113         }
114         dfs1(1,1);dfs2(1,1);
115         build(rt,1,n);char s[10];
116         for(int i=1;i<n;i++)
117         {
118             x=d[a[i].x]>d[a[i].to]?a[i].x:a[i].to;
119             change(rt,1,n,pos[x],a[i].w);
120         }
121         change(rt,1,n,pos[1],-1e9);
122         while(1)
123         {
124             scanf("%s",s);
125             if(s[0]=='D')break;
126             if(s[0]=='Q')
127             {
128                 scanf("%d%d",&x,&y);
129                 printf("%d\n",querytree(x,y));
130             }
131             else
132             {
133                 scanf("%d%d",&x,&y);
134                 x=d[a[x].x]>d[a[x].to]?a[x].x:a[x].to;
135                 change(rt,1,n,pos[x],y);
136             }
137         }
138     }
139     return 0;
140 }

 

转载于:https://www.cnblogs.com/nbwzyzngyl/p/8342507.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值