bzoj1036 [ ZJOI2008 ] --树链剖分

模板题。。。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 30001
#define INF 1000000000
inline char Nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    if(p1==p2){
        p2=(p1=buf)+fread(buf,1,100000,stdin);
        if(p1==p2)return EOF;
    }
    return *p1++;
}
inline void Read(int& x){
    char c=Nc(),b=1;
    for(;c<'0'||c>'9';c=Nc())if(c=='-')b=-1;
    for(x=0;c>='0'&&c<='9';x=x*10+c-48,c=Nc());x*=b;
}
inline void Read(char* s){
    int i=0;
    char c=Nc();
    while(c!=' ')s[i]=c,i++,c=Nc();
}
int Len;
char s[20];
inline void Print(int x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(!x){
        putchar('0');putchar('\n');
        return;
    }
    for(Len=0;x;x/=10)s[++Len]=x%10;
    for(;Len;Len--)putchar(s[Len]+48);
    putchar('\n');
}
struct Edge{
    int To,Next;
}e[N<<1];
inline int _Max(int x,int y){
    return x>y?x:y;
}
int h[N],i,j,k,Num,n,m,T,a[N],w[N],x,y,w2[N],Top[N],Size[N],Son[N],f[N],Sum[N<<2],Max[N<<2],Deep[N];
char S[20];
inline void Add(int x,int y){
    e[++Num].To=y;e[Num].Next=h[x];h[x]=Num;
}
void Dfs1(int x,int Fa){
    f[x]=Fa;Size[x]=1;Deep[x]=Deep[Fa]+1;
    for(int i=h[x];i;i=e[i].Next)
    if(e[i].To!=Fa){
        Dfs1(e[i].To,x);
        Size[x]+=Size[e[i].To];
        if(Size[e[i].To]>Size[Son[x]])Son[x]=e[i].To;
    }
}
void Dfs2(int x,int Tmp){
    w[x]=++m;w2[m]=x;Top[x]=Tmp;
    if(Son[x])Dfs2(Son[x],Tmp);
    for(int i=h[x];i;i=e[i].Next)
    if(e[i].To!=f[x]&&e[i].To!=Son[x])Dfs2(e[i].To,e[i].To);
}
void Build(int Node,int l,int r){
    if(l==r){
        Sum[Node]=Max[Node]=a[w2[l]];
        return;
    }
    int Mid=(l+r)>>1;
    Build(Node<<1,l,Mid);
    Build(Node<<1|1,Mid+1,r);
    Sum[Node]=Sum[Node<<1]+Sum[Node<<1|1];
    Max[Node]=_Max(Max[Node<<1],Max[Node<<1|1]);
}
void Update(int Node,int l,int r,int x,int y){
    if(l==r){
        Sum[Node]=Max[Node]=y;
        return;
    }
    int Mid=(l+r)>>1;
    if(x<=Mid)Update(Node<<1,l,Mid,x,y);else Update(Node<<1|1,Mid+1,r,x,y);
    Sum[Node]=Sum[Node<<1]+Sum[Node<<1|1];
    Max[Node]=_Max(Max[Node<<1],Max[Node<<1|1]);
}
int Querysum(int Node,int l,int r,int L,int R){
    if(l>R||r<L)return 0;
    if(l>=L&&r<=R)return Sum[Node];
    int Mid=(l+r)>>1;
    return Querysum(Node<<1,l,Mid,L,R)+Querysum(Node<<1|1,Mid+1,r,L,R);
}
int Querymax(int Node,int l,int r,int L,int R){
    if(l>R||r<L)return -INF;
    if(l>=L&&r<=R)return Max[Node];
    int Mid=(l+r)>>1;
    return _Max(Querymax(Node<<1,l,Mid,L,R),Querymax(Node<<1|1,Mid+1,r,L,R));
}
int Querysum_tree(int u,int v){
    int Ans=0;
    while(Top[u]!=Top[v])
    if(Deep[Top[u]]<Deep[Top[v]]){
        Ans+=Querysum(1,1,m,w[Top[v]],w[v]);
        v=f[Top[v]];
    }else{
        Ans+=Querysum(1,1,m,w[Top[u]],w[u]);
        u=f[Top[u]];
    }
    if(w[u]<w[v])Ans+=Querysum(1,1,m,w[u],w[v]);else Ans+=Querysum(1,1,m,w[v],w[u]);
    return Ans;
}
int Querymax_tree(int u,int v){
    int Ans=-INF;
    while(Top[u]!=Top[v])
    if(Deep[Top[u]]<Deep[Top[v]]){
        Ans=_Max(Ans,Querymax(1,1,m,w[Top[v]],w[v]));
        v=f[Top[v]];
    }else{
        Ans=_Max(Ans,Querymax(1,1,m,w[Top[u]],w[u]));
        u=f[Top[u]];
    }
    if(w[u]<w[v])Ans=_Max(Ans,Querymax(1,1,m,w[u],w[v]));else Ans=_Max(Ans,Querymax(1,1,m,w[v],w[u]));
    return Ans;
}
int main()
{
    Read(n);
    for(i=1;i<n;i++){
        Read(x);Read(y);
        Add(x,y);
        Add(y,x);
    }
    for(i=1;i<=n;i++)Read(a[i]);
    Dfs1(1,0);
    Dfs2(1,1);
    Build(1,1,m);
    Read(T);
    while(T--){
        Read(S);Read(x);Read(y);
        if(S[0]=='C')Update(1,1,m,w[x],y);else
        if(S[1]=='S')Print(Querysum_tree(x,y));else Print(Querymax_tree(x,y));
    }
    return 0;
}
bzoj1036

 

posted @ 2016-08-23 21:15  gjghfd  阅读(176)  评论(0编辑  收藏  举报