SPOJ GSS7 && Vijos1620 【LCT】

題意:給定一棵有點權的樹。

支持操作:

1.修改(u,v)這條路徑上的點權

2.詢問(u,v)這條路徑上的連續的點權的最大值。


這道題應該可以用樹鏈剖分做。不過鑑於我正在學LCT那就用LCT好了~

應該算是比較裸的LCT了吧。維護lmax、rmax、smax、sum即可回答。修改的時候打個標記就行。


Vijos上0.6s,SPOJ上17s。。這什麼差距。。


貼代碼~

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define inf 0x7fffffff
#define max(a,b) (((a)>(b))?(a):(b)) 
struct LinkCutTree{
    #define S 200010
    int pp[S],ch[S][2],fa[S],val[S],sz[S],lmax[S],rmax[S],smax[S],sum[S],same[S];
    
    #define ls ch[x][0]
    #define rs ch[x][1]
    inline void pushup(int x){
        sz[x]=sz[ls]+sz[rs]+1;
        sum[x]=sum[ls]+sum[rs]+val[x];
        lmax[x]=max(lmax[ls],sum[ls]+val[x]+lmax[rs]);
        rmax[x]=max(rmax[rs],sum[rs]+val[x]+rmax[ls]);
        smax[x]=max(max(smax[ls],smax[rs]),rmax[ls]+val[x]+lmax[rs]);
    }
    
    inline void pushdown(int x){
        if(same[x]!=inf){
            if(ls){
                same[ls]=val[ls]=same[x];
                sum[ls]=same[x]*sz[ls];
                lmax[ls]=rmax[ls]=smax[ls]=max(sum[ls],0);
            }
            if(rs){
                same[rs]=val[rs]=same[x];
                sum[rs]=same[x]*sz[rs];
                lmax[rs]=rmax[rs]=smax[rs]=max(sum[rs],0);
            }
            same[x]=inf;
        }
    }
    inline void rotate(int x,int f){
        int y=fa[x],z=fa[y];
        pushdown(y);
        pushdown(x);
        ch[y][!f]=ch[x][f];
        fa[ch[x][f]]=y;
        ch[z][ch[z][1]==y]=x;
        fa[x]=z;
        ch[x][f]=y;
        fa[y]=x;
        pushup(y);
    }
    
    inline void splay(int x){
        int p;
        for(p=x;fa[p];p=fa[p]);
        if(p!=x){
            pp[x]=pp[p];
            pp[p]=0;
            while(fa[x])    rotate(x,ch[fa[x]][0]==x);
            pushup(x);
        }else   pushdown(x);
    }
    
    inline void access(int x){
        for(int p=0;x;x=pp[x]){
            splay(x);   
            pp[rs]=x;   
            fa[rs]=0;
            rs=p;   
            pp[rs]=0;    
            fa[rs]=x;
            p=x;
            pushup(x);
        }
    }
       
    inline void update(int x,int y,int v){
        access(y);
        for(y=0;x;x=pp[x]){
            splay(x);
            if(!pp[x]){
                val[x]=v;
                if(y){
                    val[y]=same[y]=v;
                    sum[y]=v*sz[y];
                    lmax[y]=rmax[y]=smax[y]=max(0,v);
                }
                if(rs){
                    y=rs;
                    val[y]=same[y]=v;
                    sum[y]=v*sz[y];
                    lmax[y]=rmax[y]=smax[y]=max(0,v);
                }
            }
            pp[rs]=x;
            fa[rs]=0;
            rs=y;
            fa[rs]=x;
            pp[rs]=0;
            y=x;
            pushup(x);
        }
    }
    
    inline int query(int x,int y){
        int ans;
        access(y);
        for(y=0;x;x=pp[x]){
            splay(x);
            if(!pp[x])  return max(max(smax[y],smax[rs]),val[x]+lmax[y]+lmax[rs]);
            pp[rs]=x;
            fa[rs]=0;
            rs=y;
            fa[rs]=x;
            pp[rs]=0;
            y=x;
            pushup(x);
        }
        return 0;
    }
}LCT;

#define maxn 200010
#define maxm 400020
struct edge{
    int t,next;
}E[maxm];
int V[maxn],tot=0;

inline void addedge(int x,int y){
    E[tot].t=y;E[tot].next=V[x];V[x]=tot++;
}

int vis[maxn],q[maxn];
inline void bfs(int x){
    int head=0,tail=1;
    memset(vis,0,sizeof(vis));
    vis[x]=true;
    q[head]=x;
    while(head!=tail){
        int u=q[head++];
        for(int p=V[u];p!=-1;p=E[p].next){
            int v=E[p].t;
            if(!vis[v]){
                LCT.pp[v]=u;
                LCT.same[v]=inf;
                vis[v]=true;
                q[tail++]=v;
            }
        }
    }
}

inline void init(){
    memset(V,0xff,sizeof(V));
    tot=0;
}

inline void read(int &x){
    char ch;    int f=1;
    for(ch=getchar();(ch!='-')&&(ch<'0'||ch>'9');ch=getchar());
    if(ch=='-') f=-1,x=0;   else    x=ch-'0';
    for(ch=getchar();ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    x*=f;
}

int main(){
    int n,u,v,x,y,q,op;
    read(n); 
    init();
    for(int i=1;i<=n;i++){
        read(LCT.val[i]);
        LCT.same[i]=inf;
    }
    for(int i=1;i<n;i++){
        read(u);
        read(v);
        addedge(u,v);
        addedge(v,u);
    }
    bfs(1);
    read(q);
    int flag=0;
    while(q--){
        read(op);
        if(op==1){
            read(x);
            read(y);
            if(flag)printf(" ");    else flag=1;
            printf("%d",LCT.query(x,y));
        }else{
            read(x);
            read(y);
            read(v);
            LCT.update(x,y,v);
        }
    }
    printf("\n");
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章