• BZOJ1984: 月下“毛景树”


    题解:裸树剖+线段树

    /**************************************************************
        Problem: 1984
        User: c20161007
        Language: C++
        Result: Accepted
        Time:4852 ms
        Memory:15324 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define f first
    #define s second
    #define ll long long
    const int MAXN=1e5+10;
    using namespace std;
    int fa[MAXN],dep[MAXN],num[MAXN],son[MAXN],vis[MAXN],a[MAXN];
    vector<pair<int,pair<int,int> > >vec[MAXN];
    int n;char str[101];
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    void dfs(int v,int pre,int deep){
        fa[v]=pre;num[v]=1;dep[v]=deep+1;
        for(int i=0;i<vec[v].size();i++){
        int u=vec[v][i].f;
        if(u!=pre){
            a[u]=vec[v][i].s.f;vis[vec[v][i].s.s]=u;
            dfs(u,v,deep+1);
            num[v]+=num[u];
            if(son[v]==-1||num[son[v]]<num[u])son[v]=u;
        }
        }
    }
    int p[MAXN],tp[MAXN],fp[MAXN],cnt;
    void dfs1(int v,int td){
        p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
        if(son[v]!=-1)dfs1(son[v],td);
        for(int i=0;i<vec[v].size();i++){
        if(vec[v][i].f!=son[v]&&vec[v][i].f!=fa[v])dfs1(vec[v][i].f,vec[v][i].f);
        }
    }
    int key[MAXN<<2],flag[MAXN<<2],flag1[MAXN<<2];
    void push(int x){
        if(flag[x]>=0){
        flag1[x<<1]=flag1[x<<1|1]=0;flag[x<<1]=flag[x<<1|1]=flag[x];
        key[x<<1]=key[x<<1|1]=flag[x];
        flag[x]=-1;
        }
        if(flag1[x]){
        flag1[x<<1]+=flag1[x];flag1[x<<1|1]+=flag1[x];
        key[x<<1]+=flag1[x];key[x<<1|1]+=flag1[x];
        flag1[x]=0;
        }
    }
    void up(int x){key[x]=max(key[x<<1],key[x<<1|1]);return ;}
    void built(int rt,int l,int r){
        flag[rt]=-1;flag1[rt]=0;
        if(l==r){key[rt]=a[fp[l]];return ;}
        int mid=(l+r)>>1;
        built(rt<<1,l,mid);
        built(rt<<1|1,mid+1,r);
        up(rt);
    }
    void update1(int rt,int l,int r,int t,int vul){
        if(l==r){key[rt]=vul;return ;}
        int mid=(l+r)>>1;
        push(rt);
        if(t<=mid)update1(rt<<1,l,mid,t,vul);
        else update1(rt<<1|1,mid+1,r,t,vul);
        up(rt);
    }
    void update2(int rt,int l,int r,int ql,int qr,int t){
        if(ql<=l&&r<=qr){key[rt]=t;flag1[rt]=0;flag[rt]=t;return ;}
        int mid=(l+r)>>1;
        push(rt);
        if(ql<=mid)update2(rt<<1,l,mid,ql,qr,t);
        if(qr>mid)update2(rt<<1|1,mid+1,r,ql,qr,t);
        up(rt);
    }
    void update3(int rt,int l,int r,int ql,int qr,int t){
        if(ql<=l&&r<=qr){key[rt]+=t;flag1[rt]+=t;return ;}
        int mid=(l+r)>>1;
        push(rt);
        if(ql<=mid)update3(rt<<1,l,mid,ql,qr,t);
        if(qr>mid)update3(rt<<1|1,mid+1,r,ql,qr,t);
        up(rt);
    }
    int ans;
    void querty(int rt,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){ans=max(ans,key[rt]);return ;}
        int mid=(l+r)>>1;
        push(rt);
        if(ql<=mid)querty(rt<<1,l,mid,ql,qr);
        if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr);
        up(rt);
    }
    int slove(int u,int v,int op,int w){
        int uu=tp[u];int vv=tp[v];int ans1=-1;
        while(uu!=vv){
        if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
        if(op==1)update2(1,1,n,p[uu],p[u],w);
        else if(op==2)update3(1,1,n,p[uu],p[u],w);
        else ans=-1,querty(1,1,n,p[uu],p[u]),ans1=max(ans1,ans);
        u=fa[uu];uu=tp[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        if(u!=v){
        if(op==1)update2(1,1,n,p[son[u]],p[v],w);
        else if(op==2)update3(1,1,n,p[son[u]],p[v],w);
        else ans=-1,querty(1,1,n,p[son[u]],p[v]),ans1=max(ans1,ans);
        }
        return ans1;
    }
    int main(){
        n=read();int u,v,vul;
        for(int i=1;i<n;i++)u=read(),v=read(),vul=read(),vec[u].push_back(make_pair(v,make_pair(vul,i))),vec[v].push_back(make_pair(u,make_pair(vul,i)));
        for(int i=1;i<=n;i++)son[i]=-1;
        dfs(1,0,0);dfs1(1,1);built(1,1,n);
        //for(int i=1;i<=n;i++)cout<<num[i]<<" ";
        //cout<<endl;
        //cout<<"sb"<<endl;
        while(1){
        scanf(" %s",str);
        if(str[0]=='S')break;
        if(str[1]=='h'){
            u=read();v=read();update1(1,1,n,p[vis[u]],v);
        }
        else if(str[1]=='o'){
            u=read();v=read();vul=read();slove(u,v,1,vul);
        }
        else if(str[0]=='A'){
            u=read(),v=read(),vul=read(),slove(u,v,2,vul);
        }
        else{
            u=read();v=read();
            printf("%d
    ",slove(u,v,3,0));
        }
        }
        return 0;
    }
    
    

    1984: 月下“毛景树”

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 2438  Solved: 713
    [Submit][Status][Discuss]

    Description

    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

    Input

    第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

    Output

    对于毛毛虫的每个询问操作,输出一个答案。

    Sample Input

    4
    1 2 8
    1 3 7
    3 4 9
    Max 2 4
    Cover 2 4 5
    Add 1 4 10
    Change 1 16
    Max 2 4
    Stop

    Sample Output

    9
    16

    【Data Range】
    1<=N<=100,000,操作+询问数目不超过100,000。
    保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

     

  • 相关阅读:
    Gitlab使用腾讯企业邮箱
    查看Binlog内容
    微信小游戏手记
    clickhouse手记
    腾讯云手记
    go框架gin
    go idea debug
    go手记
    crontab手记
    Laravel-cors 跨域
  • 原文地址:https://www.cnblogs.com/wang9897/p/9347628.html
Copyright © 2020-2023  润新知