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

来源:互联网 发布:c语言联合体初始化为0 编辑:程序博客网 时间:2024/04/29 07:09

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;}




0 0
原创粉丝点击