zoukankan      html  css  js  c++  java
  • bzoj1036: [ZJOI2008]树的统计Count

    http://www.lydsy.com/JudgeOnline/problem.php?id=1036

    树链剖分板子题

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    #define N 30001
    
    using namespace std;
    
    int front[N],to[N<<1],nxt[N<<1],tot;
    
    int n,val[N];
    
    int siz[N],fa[N],dep[N];
    
    int id[N],dy[N],bl[N];
    
    int mx[N<<2],sum[N<<2];
    
    int ans;
    
    void read(int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    
    void dfs1(int x,int y)
    {
        siz[x]=1;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=y)
            {
                dep[to[i]]=dep[x]+1;
                fa[to[i]]=x;
                dfs1(to[i],x);
                siz[x]+=siz[to[i]];
            }
    }
    
    void dfs2(int x,int top)
    {
        bl[x]=top;
        id[x]=++tot; dy[tot]=x;
        int y=0;
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==fa[x]) continue;
            if(siz[to[i]]>siz[y]) y=to[i];
        }
        if(y) dfs2(y,top);
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==fa[x] || to[i]==y) continue;
            dfs2(to[i],to[i]); 
        }
    } 
    
    void build(int k,int l,int r)
    {
        if(l==r)
        {
            mx[k]=sum[k]=val[dy[l]];
            return;
        }
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
        sum[k]=sum[k<<1]+sum[k<<1|1];
    }
    
    void change(int k,int l,int r,int pos,int w)
    {
        if(l==r)
        {
            mx[k]=sum[k]=w;
            return;
        }
        int mid=l+r>>1;
        if(pos<=mid) change(k<<1,l,mid,pos,w);
        else change(k<<1|1,mid+1,r,pos,w);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
        sum[k]=sum[k<<1]+sum[k<<1|1]; 
    }
    
    void query(int k,int l,int r,int opl,int opr,bool ty)
    {
        if(l>=opl && r<=opr)
        {
            if(!ty) ans=max(ans,mx[k]);
            else ans+=sum[k];
            return;
        }
        int mid=l+r>>1;
        if(opl<=mid) query(k<<1,l,mid,opl,opr,ty);
        if(opr>mid) query(k<<1|1,mid+1,r,opl,opr,ty);
    }
    
    void solve(int u,int v,bool ty)
    {
        if(!ty) ans=-1e7; 
        else ans=0;
        while(bl[u]!=bl[v])
        {
            if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
            query(1,1,n,id[bl[u]],id[u],ty);
            u=fa[bl[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        query(1,1,n,id[u],id[v],ty);
        cout<<ans<<'
    ';
    } 
    
    int main()
    {
        int u,v;  read(n);
        for(int i=1;i<n;++i) read(u),read(v),add(u,v);
        for(int i=1;i<=n;++i) read(val[i]);
        dfs1(1,0); tot=0; dfs2(1,1);
        build(1,1,n);
        int m; char c[7];  read(m);
        while(m--)
        {
            scanf("%s",c);
            read(u); read(v);
            if(c[0]=='C') change(1,1,n,id[u],v);
            else if(c[1]=='M')  solve(u,v,0);
            else solve(u,v,1);
        }
    }

    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 19421  Solved: 7912
    [Submit][Status][Discuss]

    Description

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

      输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
    一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
    的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

      对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    Sample Input

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
  • 相关阅读:
    P1217 [USACO1.5]回文质数 Prime Palindromes
    C++ 队列(queue)堆栈(stack)实现基础
    深入理解指针—>指针函数与函数指针的区别
    C语言结构体及typedef关键字定义结构体别名和函数指针的应用
    实现常用的配置文件/初始化文件读取的一个C程序
    C语言sscanf和sprintf输入输出使用及Strlen、Memset解释
    C语言一些基础知识
    Google的开源C++单元测试框架Google Test
    网站(Web)压测工具Webbench源码分析
    web压测工具http_load原理分析
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7912352.html
Copyright © 2011-2022 走看看