您的位置:首页 > 其它

【树链剖分模板】【bzoj1036】: [ZJOI2008]树的统计Count

2014-10-20 22:01 423 查看

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 5522  Solved: 2307

[Submit][Status]

Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4

Sample Output

4

1

2

2

10

6

5

6

5

16

HINT

Source

树的分治

裸链剖,好久没写了,熟悉一下

第一个代码没写LCA,第二个代码加了LCA

时间差距不大,没有必要就不用写



//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/////////////////////////////////////////////////
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
/////////////////////////////////////////////////
const int MAXN=30010;
int n,q;
struct edge
{int v,next;}e[MAXN * 2];
int head[MAXN];
int k=0;

int w[MAXN];

int fa[MAXN];
int son[MAXN];
int dep[MAXN];
int sz[MAXN];
int top[MAXN];
int fc[MAXN];
int cnt;

int mmax[70000];
int dis[70000];
/////////////////////////////////////////////////
void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;}
void dfs1(int u,int distance)
{
son[u]=0; sz[u]=1;
dis[u]=distance;
INE(i,u,e)
{
int v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u; dep[v]=dep[u]+1;
dfs1(v,distance+w[v]);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp; fc[u]=++cnt;
if(son[u]) dfs2(son[u],tp);
INE(i,u,e)
{
int v=e[i].v;
if(v==son[u] || v==fa[u]) continue;
dfs2(v,v);
}
}

void build(int id,int l,int r)
{
mmax[id]=-99999;
if(l==r)return;
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
int query1(int id,int l,int r,int L,int R)
{
if(l<=L && R<=r) return mmax[id];
int mid=(L+R)>>1;
if(r<=mid) return query1(id<<1,l,r,L,mid);
else if(l>mid) return query1(id<<1|1,l,r,mid+1,R);
else return max(query1(id<<1,l,mid,L,mid),query1(id<<1|1,mid+1,r,mid+1,R));
}
int query2(int id,int l,int r,int L,int R)
{
if(l<=L && R<=r) return dis[id];
int mid=(L+R)>>1;
if(r<=mid) return query2(id<<1,l,r,L,mid);
else if(l>mid) return query2(id<<1|1,l,r,mid+1,R);
else return query2(id<<1,l,mid,L,mid)+query2(id<<1|1,mid+1,r,mid+1,R);
}
void modify(int id,int pos,int x,int L,int R)
{
if(L==R)
{
mmax[id]=x;
dis[id]=x;
return;
}
int mid=(L+R)>>1;
if(pos<=mid) modify(id<<1,pos,x,L,mid);
else modify(id<<1|1,pos,x,mid+1,R);
mmax[id]=max(mmax[id<<1],mmax[id<<1|1]);
dis[id]=dis[id<<1]+dis[id<<1|1];
}
/*int LCA(int a,int b)
{
int ta=top[a],tb=top[b];
while(ta!=tb)
{
if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb);
a=fa[ta]; ta=top[a];
}
if(dep[a]<dep[b]) return a;
else return b;
}*/
int getmax(int a,int b)
{
int ta=top[a],tb=top[b];
int ans=w[a];
while(ta!=tb)
{
if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb);
ans=max(ans,query1(1,fc[ta],fc[a],1,cnt));
a=fa[ta]; ta=top[a];
}
if(dep[a]>dep[b]) swap(a,b);
return max(ans,query1(1,fc[a],fc[b],1,cnt));
}
int getdis(int a,int b)
{
int ta=top[a],tb=top[b];
int ans=0;
while(ta!=tb)
{
if(dep[ta]<dep[tb])swap(a,b),swap(ta,tb);
ans+=query2(1,fc[ta],fc[a],1,cnt);
a=fa[ta]; ta=top[a];
}
if(dep[a]>dep[b])swap(a,b);
return ans+query2(1,fc[a],fc[b],1,cnt);
}
/////////////////////////////////////////////////
void input()
{
MS(head,-1);

scanf("%d",&n);
int u,v;
rep(i,1,n-1)
{
scanf("%d%d",&u,&v);
adde(u,v); adde(v,u);
}
rep(i,1,n) scanf("%d",&w[i]);
scanf("%d",&q);
}
void solve()
{
///////////////////init///////////////////
char op[10];
int u,v;
////////////////calculate////////////////
// init HLT
dfs1(1,w[1]);
dfs2(1,1);
build(1,1,n);
rep(i,1,n) modify(1,fc[i],w[i],1,n);
/*rep(i,1,n) printf("%d\n",query(1,fc[i],fc[i],1,cnt));
return;*/
// query
while(q--)
{
scanf("%s%d%d",op,&u,&v);
if(op[0]=='C')//CHANGE
{
w[u]=v;
modify(1,fc[u],v,1,n);
}
else
{

if(op[1]=='M') //QMAX
printf("%d\n",getmax(u,v));
else ///QSUM
printf("%d\n",getdis(u,v));
}
}
/////////////////output/////////////////

}
/////////////////////////////////////////////////
int main()
{
#ifndef _TEST
freopen("1036.in","r",stdin); freopen("1036.out","w",stdout);
#endif
input();
solve();
#ifdef _TEST
for(;;);
#endif
return 0;
}




//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/////////////////////////////////////////////////
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
/////////////////////////////////////////////////
const int MAXN=30010;
int n,q;
struct edge
{int v,next;}e[MAXN * 2];
int head[MAXN];
int k=0;

int w[MAXN];

int fa[MAXN];
int son[MAXN];
int dep[MAXN];
int sz[MAXN];
int top[MAXN];
int fc[MAXN];
int cnt;

int mmax[70000];
int dis[70000];
/////////////////////////////////////////////////
void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;}
void dfs1(int u,int distance)
{
son[u]=0; sz[u]=1;
dis[u]=distance;
INE(i,u,e)
{
int v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u; dep[v]=dep[u]+1;
dfs1(v,distance+w[v]);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp; fc[u]=++cnt;
if(son[u]) dfs2(son[u],tp);
INE(i,u,e)
{
int v=e[i].v;
if(v==son[u] || v==fa[u]) continue;
dfs2(v,v);
}
}

void build(int id,int l,int r)
{
mmax[id]=-99999;
if(l==r)return;
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
int query1(int id,int l,int r,int L,int R)
{
if(l<=L && R<=r)
{
return mmax[id];
}
int mid=(L+R)>>1;
if(r<=mid) return query1(id<<1,l,r,L,mid);
else if(l>mid) return query1(id<<1|1,l,r,mid+1,R);
else return max(query1(id<<1,l,mid,L,mid),query1(id<<1|1,mid+1,r,mid+1,R));
}
int query2(int id,int l,int r,int L,int R)
{
if(l<=L && R<=r)
{
return dis[id];
}
int mid=(L+R)>>1;
if(r<=mid) return query2(id<<1,l,r,L,mid);
else if(l>mid) return query2(id<<1|1,l,r,mid+1,R);
else return query2(id<<1,l,mid,L,mid)+query2(id<<1|1,mid+1,r,mid+1,R);
}
void modify(int id,int pos,int x,int L,int R)
{
if(L==R)
{
mmax[id]=x;
dis[id]=x;
return;
}
int mid=(L+R)>>1;
if(pos<=mid) modify(id<<1,pos,x,L,mid);
else modify(id<<1|1,pos,x,mid+1,R);
mmax[id]=max(mmax[id<<1],mmax[id<<1|1]);
dis[id]=dis[id<<1]+dis[id<<1|1];
}
int LCA(int a,int b)
{
int ta=top[a],tb=top[b];
while(ta!=tb)
{
if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb);
a=fa[ta]; ta=top[a];
}
if(dep[a]<dep[b]) return a;
else return b;
}
int getmax(int a,int b)
{
int ta=top[a],tb=top[b];
int ans=w[a];
while(ta!=tb)
{
ans=max(ans,query1(1,fc[ta],fc[a],1,cnt));
a=fa[ta]; ta=top[a];
}
if(a!=b)
{
ans=max(ans,query1(1,fc[b],fc[a],1,cnt));
}
ans=max(ans,w[b]);
return ans;
}
int getdis(int a,int b)
{
int ta=top[a],tb=top[b];
int ans=0;
while(ta!=tb)
{
ans+=query2(1,fc[ta],fc[a],1,cnt);
a=fa[ta]; ta=top[a];
}
ans+=query2(1,fc[b],fc[a],1,cnt);
return ans;
}
/////////////////////////////////////////////////
void input()
{
MS(head,-1);

scanf("%d",&n);
int u,v;
rep(i,1,n-1)
{
scanf("%d%d",&u,&v);
adde(u,v); adde(v,u);
}
rep(i,1,n)
{
scanf("%d",&w[i]);
}
scanf("%d",&q);
}
void solve()
{
///////////////////init///////////////////
char op[10];
int u,v;
////////////////calculate////////////////
// init HLT
dfs1(1,w[1]);
dfs2(1,1);
build(1,1,n);
rep(i,1,n) modify(1,fc[i],w[i],1,n);
/*rep(i,1,n) printf("%d\n",query(1,fc[i],fc[i],1,cnt));
return;*/
// query
while(q--)
{
scanf("%s%d%d",op,&u,&v);
if(op[0]=='C')//CHANGE
{
w[u]=v;
modify(1,fc[u],v,1,n);
}
else
{
int lca=LCA(u,v);
if(op[1]=='M') //QMAX
{
int ans=getmax(u,lca);
ans=max(ans,getmax(v,lca));
printf("%d\n",ans);
}
else ///QSUM
{
int ans=getdis(u,lca)+getdis(v,lca);
ans-=w[lca];
printf("%d\n",ans);
}
}
}
/////////////////output/////////////////

}
/////////////////////////////////////////////////
int main()
{
#ifndef _TEST
freopen("1036.in","r",stdin); freopen("1036.out","w",stdout);
#endif
input();
solve();
#ifdef _TEST
for(;;);
#endif
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: