zoukankan      html  css  js  c++  java
  • BZOJ 1036 树的统计

    这个故事告诉我们数组开小了真的要命。

    树剖模板题。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define maxv 80005
    #define maxn 3000005
    using namespace std;
    long long w[maxv],fath[maxv],top[maxv],son[maxv],size[maxv],dis[maxv];
    long long tot=0,lson[maxn],rson[maxn],v1[maxn],v2[maxn],cnt=0;
    long long nume=0,n,a,b,q,g[maxv],c[maxv],root;
    char type[10];
    struct edge
    {
    long long v,nxt;
    }e[maxv];
    void addedge(long long u,long long v)
    {
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
    }
    void dfs1(long long x)
    {
    size[x]=1;son[x]=0;
    for (long long i=g[x];i;i=e[i].nxt)
    {
    long long v=e[i].v;
    if (v!=fath[x])
    {
    dis[v]=dis[x]+1;
    fath[v]=x;
    dfs1(v);
    if (size[son[x]]<size[v])
    son[x]=v;
    size[x]=size[x]+size[v];
    }
    }
    }
    void dfs2(long long x,long long fa)
    {
    w[x]=++tot;top[x]=fa;
    if (son[x]!=0)
    dfs2(son[x],fa);
    for (long long i=g[x];i;i=e[i].nxt)
    {
    long long v=e[i].v;
    if ((v!=fath[x]) && (v!=son[x]))
    dfs2(v,v);
    }
    }
    long long build(long long left,long long right)
    {
    long long now=++cnt;
    if (left==right)
    return now;
    long long mid=(left+right)>>1;
    lson[now]=build(left,mid);
    rson[now]=build(mid+1,right);
    v1[now]=0;
    v2[now]=0;
    return now;
    }
    void single_modify(long long now,long long left,long long right,long long pos,long long x)
    {
    if (left==right)
    {
    v1[now]=x;
    v2[now]=x;
    return;
    }
    else
    {
    long long mid=(left+right)>>1;
    if (pos<=mid)
    single_modify(lson[now],left,mid,pos,x);
    else single_modify(rson[now],mid+1,right,pos,x);
    v1[now]=v1[lson[now]]+v1[rson[now]];
    v2[now]=max(v2[lson[now]],v2[rson[now]]);
    return;
    }
    }
    long long ask1(long long now,long long left,long long right,long long l,long long r)
    {
    if ((left==l) && (right==r))
    return v1[now];
    long long mid=(left+right)>>1;
    if (r<=mid) return ask1(lson[now],left,mid,l,r);
    else if (l>=mid+1) return ask1(rson[now],mid+1,right,l,r);
    else return ask1(lson[now],left,mid,l,mid)+ask1(rson[now],mid+1,right,mid+1,r);
    }
    long long ask2(long long now,long long left,long long right,long long l,long long r)
    {
    if ((left==l) && (right==r))
    return v2[now];
    long long mid=(left+right)>>1;
    if (r<=mid) return ask2(lson[now],left,mid,l,r);
    else if (l>=mid+1) return ask2(rson[now],mid+1,right,l,r);
    else return max(ask2(lson[now],left,mid,l,mid),ask2(rson[now],mid+1,right,mid+1,r));
    }
    void work()
    {
    scanf("%s",type);
    if (type[0]=='C')
    {
    scanf("%lld%lld",&a,&b);
    single_modify(root,1,tot,w[a],b);
    c[a]=b;
    }
    else if (type[1]=='M')
    {
    scanf("%lld%lld",&a,&b);
    if (a==b) {printf("%lld ",c[a]);return;}
    long long f1,f2,ans=-10000000000;
    f1=top[a];f2=top[b];
    while (f1!=f2)
    {
    if (dis[f1]<dis[f2])
    {
    swap(f1,f2);
    swap(a,b);
    }
    ans=max(ans,ask2(root,1,tot,w[f1],w[a]));
    a=fath[f1];f1=top[a];
    }
    if (a!=b)
    {
    if (dis[a]>dis[b])
    swap(a,b);
    ans=max(ans,ask2(root,1,tot,w[a],w[b]));
    }
    printf("%lld ",max(ans,c[b]));
    }
    else
    {
    scanf("%lld%lld",&a,&b);
    if (a==b) {printf("%lld ",c[a]);return;}
    long long f1,f2,ans=0;
    f1=top[a];f2=top[b];
    while (f1!=f2)
    {
    if (dis[f1]<dis[f2])
    {
    swap(f1,f2);
    swap(a,b);
    }
    ans=ans+ask1(root,1,tot,w[f1],w[a]);
    a=fath[f1];f1=top[a];
    }
    if (a!=b)
    {
    if (dis[a]>dis[b])
    swap(a,b);
    ans=ans+ask1(root,1,tot,w[son[a]],w[b]);
    }
    printf("%lld ",ans+c[a]);
    }
    return;
    }
    int main()
    {
    memset(g,0,sizeof(g));
    memset(size,0,sizeof(size));
    scanf("%lld",&n);
    for (long long i=1;i<=n-1;i++)
    {
    scanf("%lld%lld",&a,&b);
    addedge(a,b);
    addedge(b,a);
    }
    for (long long i=1;i<=n;i++)
    scanf("%lld",&c[i]);
    dis[1]=0;
    dfs1(1);
    dfs2(1,1);
    root=build(1,tot);
    for (long long i=1;i<=n;i++)
    single_modify(root,1,tot,w[i],c[i]);
    scanf("%lld",&q);
    for (long long i=1;i<=q;i++)
    work();
    return 0;
    }

  • 相关阅读:
    VC实现开机自启动
    用Shell扩展实现源代码统计程序
    在(CListView)列表视图中添加右键菜单的方法
    关于打开外部程序并且发送一个按键消息 (转
    vc中运行外部程序的方法
    如何在 XCode 4.2 設定部分程式碼不使用 ARC 方式分享(转)
    Xcode调试断点不停止解决方案!(转)
    NSString+NSMutableString+NSValue+NSAraay用法汇总 (转)
    对于Retain和Assign属性的理解(转)
    基于Xcode4开发第一个iPhone程序:“Hello World”(转)
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5187538.html
Copyright © 2011-2022 走看看