【SPOJ375】Query on a tree-树链剖分

题目大意:有一棵树,每条边有边权,有两种操作:1.修改某条边的边权。2.询问某两个点之间路径上的所有边的边权的最大值。对于每个询问,给出正确的答案。

做法:树链剖分的模板题,注意细节就可以了。

(我竟然把query里面的a=f[top[a]]写成了a=top[a],结果做了一个多礼拜都没过......)

以下是本人代码(写的超烂...):

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 999999999
using namespace std;
int t,n,tot,f[10010],siz[10010],dep[10010],pos[10010],p,a,b,c;
int d[10010][3],first[10010],son[10010],top[10010],root;
int qpos[10010];
char op[10];
struct edge
{
  int v,next;
}e[20010];
int seg[40010];

int maximum(int a,int b)
{
  if (a>b) return a;
  else return b;
}

void readin(int a,int b,int c)
{
  e[++tot].v=b;
  e[tot].next=first[a];
  first[a]=tot;
}

void dfs1(int now)
{
  siz[now]=1;son[now]=0;
  for(int i=first[now];i>0;i=e[i].next)
    if (e[i].v!=f[now])
	{
	  dep[e[i].v]=dep[now]+1;
	  f[e[i].v]=now;
	  dfs1(e[i].v);
	  siz[now]+=siz[e[i].v];
	  if (siz[e[i].v]>siz[son[now]]) son[now]=e[i].v;
	}
}

void dfs2(int now,int chain)
{
  pos[now]=++p;top[now]=chain;
  if (son[now]) dfs2(son[now],chain);
  for(int i=first[now];i>0;i=e[i].next)
    if (e[i].v!=f[now]&&e[i].v!=son[now])
	  dfs2(e[i].v,e[i].v);
}

void buildtree(int no,int l,int r)
{
  int mid=(l+r)>>1;
  if (l==r) {seg[no]=d[qpos[l]][2];return;}
  buildtree(no<<1,l,mid);
  buildtree((no<<1)+1,mid+1,r);
  seg[no]=maximum(seg[no<<1],seg[(no<<1)+1]);
}

void change(int no,int l,int r,int a,int c)
{
  int mid=(l+r)>>1;
  if (l>a||r<a) return;
  if (l==r) {seg[no]=c;return;}
  change(no<<1,l,mid,a,c);
  change((no<<1)+1,mid+1,r,a,c);
  seg[no]=maximum(seg[no<<1],seg[(no<<1)+1]);
}

int querymx(int no,int l,int r,int s,int t)
{
  int mid=(l+r)>>1;
  if (t<l||r<s) return 0;
  if (l>=s&&r<=t) return seg[no];
  return maximum(querymx(no<<1,l,mid,s,t),querymx((no<<1)+1,mid+1,r,s,t));
}

int query(int a,int b)
{
  int mx=-inf;
  while(top[a]!=top[b])
  {
    if (dep[top[a]]<dep[top[b]]) swap(a,b);
	mx=maximum(mx,querymx(1,1,p,pos[top[a]],pos[a]));
	a=f[top[a]];
  }
  if (dep[a]<dep[b]) swap(a,b);
  if (a!=b) mx=maximum(mx,querymx(1,1,p,pos[son[b]],pos[a]));
  return mx;
}

void read()
{
  op[0]=' ';
  while (op[0]<'C'||op[0]>'Q') scanf("%s",op);
}

void input()
{
  scanf("%d",&n);
  root=(n+1)/2;
  memset(first,0,sizeof(first));
  memset(seg,0,sizeof(seg));
  tot=f[root]=dep[root]=p=0;
  for(int i=1;i<=n-1;i++)
  {
    scanf("%d %d %d",&a,&b,&c);
	d[i][0]=a;d[i][1]=b;d[i][2]=c;
	readin(a,b,c);readin(b,a,c);
  }
  dfs1(root);
  dfs2(root,root);
  for(int i=1;i<n;i++)
  {
	if (dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
	qpos[pos[d[i][1]]]=i;
  }
  buildtree(1,1,p);
}

void work()
{
  int a,b;
  for(read();op[0]!='D';read())
  {
    scanf("%d %d",&a,&b);
    if (op[0]=='Q') printf("%d
",query(a,b));
	else change(1,1,p,pos[d[a][1]],b);
  }
}

int main()
{
  for(scanf("%d",&t);t>0;t--)
  {
    input();
	work();
  }
  
  return 0;
}


原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793962.html