您的位置:首页 > 其它

BZOJ 1036([ZJOI2008]树的统计Count-树链剖分[成熟版])

2013-07-07 12:54 501 查看

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec Memory Limit: 162 MB

Submit: 3205 Solved: 1335

[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

在yzc的RP++模板下:

我完成了成熟版的树链剖分

本次更新的主要内容:

1.趋向于把值存在点上

2.引入了dfs序的概念

3.成功的只建一棵线段树,从此和可持久化说再见

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (30000+10)
#define MAXM (200000+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int n,m;
ll sum[MAXN<<3]={0},maxv[MAXN<<3]={0};
void update(int x){sum[x]=sum[Lson]+sum[Rson],maxv[x]=max(maxv[Lson],maxv[Rson]);}
void change(int x,int l,int r,int L,int c)
{
if (l==r) {sum[x]=maxv[x]=c;return;}
int m=l+r>>1;
if (L<=m) change(Lson,l,m,L,c);
else change(Rson,m+1,r,L,c);
update(x);
}
ll qurrysum(int x,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return sum[x];
int m=l+r>>1;
ll ans=0;
if (L<=m) ans+=qurrysum(Lson,l,m,L,R);
if (m<R) ans+=qurrysum(Rson,m+1,r,L,R);
return ans;
}
ll qurrymax(int x,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return maxv[x];
int m=l+r>>1;
ll ans=-INF;
if (L<=m) ans=max(ans,qurrymax(Lson,l,m,L,R));
if (m<R) ans=max(ans,qurrymax(Rson,m+1,r,L,R));
return ans;
}
int edge[MAXN*2],pre[MAXN]={0},next[MAXN*2]={0},size=0;
void addedge(int u,int v)
{
edge[++size]=v;
next[size]=pre[u];
pre[u]=size;
}
void addedge2(int u,int v){addedge(u,v),addedge(v,u);}
int dep[MAXN]={0},siz[MAXN]={0},opt[MAXN]={0},father[MAXN]={0};
void dfs(int x)
{
siz[x]=1;
dep[x]=dep[father[x]]+1;
Forp(x)
{
int &v=edge[p];
if (v^father[x])
{
father[v]=x;
dfs(v);
siz[x]+=siz[v];
if (siz[v]>siz[opt[x]]) opt[x]=v;
}
}
}
int top[MAXN],w[MAXN],place[MAXN],tim=0;
void dfs2(int x,int chain)
{
top[x]=chain;
place[x]=++tim;
change(1,1,n,place[x],w[x]);
if (opt[x]) dfs2(opt[x],chain);else return;
Forp(x)
{
int &v=edge[p];
if (v^father[x]&&v^opt[x])
{
dfs2(v,v);
}
}
}
ll lca_sum(int u,int v)
{
ll ans=0;
while (top[u]^top[v])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
ans+=qurrysum(1,1,n,place[top[u]],place[u]);
u=father[top[u]];
}
if (dep[u]<dep[v]) swap(u,v);
ans+=qurrysum(1,1,n,place[v],place[u]);
return ans;
}
ll lca_max(int u,int v)
{
ll ans=-INF;
while (top[u]^top[v])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
ans=max(ans,qurrymax(1,1,n,place[top[u]],place[u]));
u=father[top[u]];
}
if (dep[u]<dep[v]) swap(u,v);
ans=max(ans,qurrymax(1,1,n,place[v],place[u]));
return ans;
}
char c[10];
int main()
{
//	freopen("bzoj1036.in","r",stdin);
scanf("%d",&n);
/*
For(i,n)
{
int p,l,r,c;
cin>>p>>l>>r;
if (p==1) change(1,1,n,l,r);
if (p==2) cout<<qurrysum(1,1,n,l,r)<<endl;
if (p==3) cout<<qurrymax(1,1,n,l,r)<<endl;

}*/
For(i,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
addedge2(u,v);
}
For(i,n) scanf("%d",&w[i]);
dfs(1);
dfs2(1,1);
scanf("%d",&m);
For(i,m)
{
int a,b;
scanf("%s%d%d",c,&a,&b);
switch(c[1])
{
case'H':change(1,1,n,place[a],b);break;
case'S':printf("%lld\n",lca_sum(a,b));break;
case'M':printf("%lld\n",lca_max(a,b));
}
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: