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\n",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个。

 

posted @ 2018-07-21 18:56  wang9897  阅读(133)  评论(0编辑  收藏  举报