码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ1984] 月下“毛景树”|树链剖分|线段树

时间:2015-08-11 21:16:36      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:

1984: 月下“毛景树”

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 1088  Solved: 348
[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个。

HINT

 

Source

 
1071046 ws_fqk 1984 Wrong_Answer 44644 kb 904 ms C++/Edit 5488 B 2015-08-11 19:22:07
1071034 ws_fqk 1984 Wrong_Answer 44644 kb 924 ms C++/Edit 5470 B 2015-08-11 19:15:21
1071019 ws_fqk 1984 Wrong_Answer 42304 kb 960 ms C++/Edit 5312 B 2015-08-11 19:08:32
1071018 ws_fqk 1984 Wrong_Answer 43464 kb 92 ms C++/Edit 4179 B 2015-08-11 19:07:15
1071006 ws_fqk 1984 Time_Limit_Exceed kb ms C++/Edit 5314 B 2015-08-11 18:55:07
1071002 ws_fqk 1984 Time_Limit_Exceed kb ms C++/Edit 5308 B 2015-08-11 18:51:23
1070994 ws_fqk 1984 Runtime_Error 21988 kb 976 ms C++/Edit 5308 B 2015-08-11 18:42:40

已经给跪了……

 

大体思路就是把边权压到点上,具体做法可以自己YY,询问时处理一下就好。hzwer学长是压到了深度小的点,我是压到了深度大的点。

调了一晚上没过……不管了。

未AC代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define N 100005
using namespace std;
int head[N],next[2*N],list[2*N],key[2*N];
int l[4*N],r[4*N],tagadd[4*N],tagchange[4*N],size[N],mx[4*N],c[N],fa[N][20],deep[N],id[N],belong[N];
int n,cnt,dfn;
struct node {int u,v,w;} e[N];
char ch[10];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1; c=getchar();}
    while (c>=0&&c<=9) {a=a*10+c-0; c=getchar();}
    return a*f;
}
inline void insert(int x,int y,int z)
{
    next[++cnt]=head[x];
    head[x]=cnt;
    list[cnt]=y;
    key[cnt]=z;
}
void dfs1(int x)
{
    size[x]=1;
    for (int i=1;(1<<i)<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    for (int i=head[x];i;i=next[i])
    {
        if (list[i]==fa[x][0]) continue;
        fa[list[i]][0]=x;
        c[list[i]]=key[i];
        deep[list[i]]=deep[x]+1;
        dfs1(list[i]);
        size[x]+=size[list[i]];
    }
}
void dfs2(int x,int chain)
{
    belong[x]=chain;
    id[x]=++dfn;
    int k=0;
    for (int i=head[x];i;i=next[i])
        if (list[i]!=fa[x][0]&&size[list[i]]>size[k]) k=list[i];
    if (!k) return;
    dfs2(k,chain);
    for (int i=head[x];i;i=next[i])
        if (list[i]!=fa[x][0]&&list[i]!=k) dfs2(list[i],list[i]);
}
inline int lca(int x,int y)
{
    if (deep[x]<deep[y]) swap(x,y);
    int t=deep[x]-deep[y];
    for (int i=0;(1<<i)<=t;i++)
        if ((1<<i)&t) x=fa[x][i];
    for (int i=18;i>=0;i--)
        if (fa[x][i]!=fa[y][i]) {x=fa[x][i]; y=fa[y][i];}
    return x==y?x:fa[x][0];
}
void build(int k,int x,int y)
{
    l[k]=x; r[k]=y; tagchange[k]=-1;
    if (x==y) return;
    int mid=(x+y)>>1;
    build(k<<1,x,mid); build(k<<1|1,mid+1,y);
}
inline void pushup(int k)
{
    mx[k]=max(mx[k<<1],mx[k<<1|1]);
}
inline void pushdown(int k)
{
    if (l[k]==r[k]) return;
    if (tagchange[k]!=-1)
    {
        tagadd[k<<1]=tagadd[k<<1|1]=0;
        tagchange[k<<1]=tagchange[k<<1|1]=tagchange[k];
        mx[k<<1]=mx[k<<1|1]=tagchange[k];
        tagchange[k]=-1;
    }
    if (tagadd[k])
    {
        mx[k<<1]+=tagadd[k]; mx[k<<1|1]+=tagadd[k];
        if (tagchange[k<<1]!=-1) tagchange[k<<1]+=tagadd[k]; else tagadd[k<<1]+=tagadd[k];
        if (tagchange[k<<1|1]!=-1) tagchange[k<<1|1]+=tagadd[k]; else tagadd[k<<1|1]+=tagadd[k];
        tagadd[k]=0;
    }
}
void change(int k,int x,int y,int v)
{
    pushdown(k);
    if (l[k]==x&&r[k]==y)
    {
        tagchange[k]=mx[k]=v;
        return;
    }
    int mid=(l[k]+r[k])>>1;
    if (y<=mid) change(k<<1,x,y,v);
    else if (x>mid) change(k<<1|1,x,y,v);
    else 
    {
        change(k<<1,x,mid,v);
        change(k<<1|1,mid+1,y,v);
    }
    pushup(k);
}
void add(int k,int x,int y,int v)
{
    pushdown(k);
    if (l[k]==x&&r[k]==y)
    {
        tagadd[k]=v;
        mx[k]+=v;
        return;
    }
    int mid=(l[k]+r[k])>>1;
    if (y<=mid) add(k<<1,x,y,v);
    else if (x>mid) add(k<<1|1,x,y,v);
    else
    {
        add(k<<1,x,mid,v);
        add(k<<1|1,mid+1,y,v);
    }
    pushup(k);
}
int getmx(int k,int x,int y)
{
    pushdown(k);
    if (l[k]==x&&r[k]==y) return mx[k];
    int mid=(l[k]+r[k])>>1;
    if (mid>=y) return getmx(k<<1,x,y);
    else if (mid<x)return getmx(k<<1|1,x,y);
    else return max(getmx(k<<1,x,mid),getmx(k<<1|1,mid+1,y));
}
inline void solvechange(int x,int f,int w)
{
    if (x==f) return;
    while (belong[x]!=belong[f])
    {
        change(1,id[belong[x]],id[x],w);
        x=fa[belong[x]][0];
    }
    if (x==f) return; int k=0;
    for (int i=head[f];i;i=next[i])
        if (list[i]!=fa[f][0]&&fa[lca(list[i],x)][0]==f) k=list[i];
    change(1,id[k],id[x],w);
}
inline int solvemax(int x,int f)
{
    if (x==f) return -1;
    int ans=-1;
    while (belong[x]!=belong[f])
    {
        ans=max(ans,getmx(1,id[belong[x]],id[x]));
        x=fa[belong[x]][0];
    }
    if (x==f) return ans; int k=0;
    for (int i=head[f];i;i=next[i])
        if (list[i]!=fa[f][0]&&fa[lca(list[i],x)][0]==f) k=list[i];
    return max(ans,getmx(1,id[k],id[x]));
}
inline void solveadd(int x,int f,int w)
{
    if (x==f) return;
    while (belong[x]!=belong[f])
    {
        add(1,id[belong[x]],id[x],w);
        x=fa[belong[x]][0];
    }
    if (x==f) return; int k=0;
    for (int i=head[f];i;i=next[i])
        if (list[i]!=fa[f][0]&&fa[lca(list[i],x)][0]==f) k=list[i];
    add(1,id[k],id[x],w);
}
int main()
{
    n=read();
    for (int i=1;i<n;i++)
    {
        e[i].u=read(),e[i].v=read(),e[i].w=read();
        insert(e[i].u,e[i].v,e[i].w); insert(e[i].v,e[i].u,e[i].w);
    }
    dfs1(1); dfs2(1,1); build(1,1,n);    
    for (int i=1;i<=n;i++) change(1,id[i],id[i],c[i]);
    while (1)
    {
        scanf("%s",ch); 
        if (ch[1]==t) break;
        int u=read(),v=read(),t,w,ans=-1;
        if (ch[1]==a) {t=lca(u,v); if (t!=v&&t!=u&&t!=1) ans=getmx(1,id[t],id[t]); ans=max(ans,max(solvemax(u,t),solvemax(v,t))); printf("%d\n",ans);}
        if (ch[1]==o) {w=read(); t=lca(u,v); solvechange(u,t,w); solvechange(v,t,w); if (t!=v&&t!=u&&t!=1) change(1,id[t],id[t],w);}
        if (ch[1]==d) {w=read(); t=lca(u,v); solveadd(u,t,w); solveadd(v,t,w); if (t!=v&&t!=u&&t!=1) add(1,id[t],id[t],w);} 
        if (ch[1]==h) {if (deep[e[u].v]<deep[e[u].u]) change(1,id[e[u].u],id[e[u].u],v); else change(1,id[e[u].v],id[e[u].v],v);}
    }
    return 0;
}

 

[BZOJ1984] 月下“毛景树”|树链剖分|线段树

标签:

原文地址:http://www.cnblogs.com/ws-fqk/p/4722110.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!