• HDOJ5692解题报告【dfs序+线段树】


    题目地址:

      http://acm.hdu.edu.cn/showproblem.php?pid=5692

    题目概述:

      中文题面就不赘述了。

    大致思路:

      这个题给出的是一棵树,我们可以使用dfs序将这棵树处理成一条链,然后对这条链来进行信息维护和查询。

      有两种操作,0 x是询问从0出发(题目保证0为树根)经过x的路径中的最大权值,1 x y是将点x的权值修改成y,这时我们用线段树来维护一个d[i]表示点i到0点的权值和。

      对于第一种操作就是查询x及其子树上的最大值,经过dfs序的处理之后这是一段连续的区间,求一个最大值即可。

      对于第二种操作我们只需要在x及其子树上add一个y-a[x]即可。

      注意可能爆栈,记得按题目里的提示处理。

    复杂度分析:

      dfs序是O(n),线段树查询跟区间修改是O(logn),建树O(nlogn),综上O(nlogn*T)

    代码:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <ctime>
    #include <map>
    #include <assert.h>
    #include <stack>
    #include <set>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define sacnf scanf
    #define scnaf scanf
    #define maxn 100010
    #define maxm 18
    //#define inf 1061109567
    const long long inf=1e15;
    #define INF 0x3f3f3f3f
    #define Eps 0.000001
    const double PI=acos(-1.0);
    #define mod 1000000007
    #define MAXNUM 10000
    #define For(i,j,k) for(int (i)=(j);(i)<=(k);(i)++)
    #define mes(a,b) memset((a),(b),sizeof(a))
    #define scanfi(a) scanf("%d",&(a))
    typedef long long ll;
    typedef unsigned long long ulld;
    void Swap(int &a,int &b) {int t=a;a=b;b=t;}
    ll Abs(ll x) {return (x<0)?-x:x;}
    struct node
    {
        ll Add,Max;
    } tree[maxn*3];
    
    vector<int> G[maxn];
    int dfs_clock,pre[maxn],low[maxn],turn[maxn];
    ll d[maxn],a[maxn];
    
    void dfs(int u,ll sum)
    {
        if(pre[u]) return;
        pre[u]=++dfs_clock;
        int len=G[u].size();
        For(i,0,len-1)
        {
            int v=G[u][i];
            dfs(v,sum+a[u]);
        }
        low[u]=dfs_clock;d[pre[u]]=sum+a[u];
        turn[u]=pre[u];
    }
    
    void build_tree(int l,int r,int dir)
    {
        if(l==r)
        {
            tree[dir].Add=0;
            tree[dir].Max=d[l];
            return;
        }
        int m=(l+r)>>1;
        build_tree(l,m,dir*2);
        build_tree(m+1,r,dir*2+1);
        tree[dir].Add=0;
        tree[dir].Max=max(tree[dir*2].Max,tree[dir*2+1].Max);
    }
    
    void add_in(int dir,ll val)
    {
        tree[dir].Add+=val;
        tree[dir].Max+=val;
    }
    
    void push_down(int dir)
    {
        if(tree[dir].Add!=0)
        {
            add_in(dir*2,tree[dir].Add);
            add_in(dir*2+1,tree[dir].Add);
            tree[dir].Add=0;
        }
    }
    
    void maintain(int dir)
    {
        tree[dir].Max=max(tree[dir*2].Max,tree[dir*2+1].Max);
    }
    
    void add(int l,int r,int dir,int al,int ar,ll val)
    {
        if(al<=l&&r<=ar) {add_in(dir,val);return;}
        push_down(dir);
        int m=(l+r)>>1;
        if(al<=m) add(l,m,dir*2,al,ar,val);
        if(ar>m) add(m+1,r,dir*2+1,al,ar,val);
        maintain(dir);
    }
    
    ll ans;
    
    void query(int l,int r,int dir,int ql,int qr)
    {
        if(ql<=l&&r<=qr) {ans=max(ans,tree[dir].Max);return;}
        push_down(dir);
        int m=(l+r)>>1;
        if(ql<=m) query(l,m,dir*2,ql,qr);
        if(qr>m) query(m+1,r,dir*2+1,ql,qr);
        maintain(dir);
    }
    
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        //clock_t st=clock();
        int T;scanfi(T);
        For(kase,1,T)
        {
            printf("Case #%d:
    ",kase);
            int n,m;scanf("%d%d",&n,&m);
            For(i,1,n)
            {
                G[i].clear();d[i]=turn[i]=0;
                pre[i]=low[i]=dfs_clock=0;
            }
            For(i,1,n-1)
            {
                int x,y;scanf("%d%d",&x,&y);
                x++;y++;G[x].push_back(y);
                G[y].push_back(x);
            }
            For(i,1,n) scanf("%lld",&a[i]);
            dfs(1,0);build_tree(1,n,1);
            //cout<<endl;For(i,1,n) printf("%d
    ",d[i]);cout<<endl;
            int opt,x;ll y;
            while(m--)
            {
                scanfi(opt);
                if(opt==0)
                {
                    scanf("%d%lld",&x,&y);x++;
                    add(1,n,1,pre[x],low[x],y-a[x]);a[x]=y;
                }
                else if(opt==1)
                {
                    scanfi(x);x++;ans=-inf;
                    query(1,n,1,pre[x],low[x]);
                    printf("%lld
    ",ans);
                }
            }
        }
        //clock_t ed=clock();
        //printf("
    
    Time Used : %.5lf Ms.
    ",(double)(ed-st)/CLOCKS_PER_SEC);
        return 0;
    }
  • 相关阅读:
    javaweb学习总结(二十三)——jsp自定义标签开发入门
    javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册
    MyEclipse使用总结——设置MyEclipse使用的Tomcat服务器
    XML学习总结(二)——XML入门
    XML学习总结(一)——XML介绍
    使用java中replaceAll方法替换字符串中的反斜杠
    MyEclipse使用总结——设置MyEclipse开发项目时使用的JDK
    MyEclipse使用总结——修改MyEclipse默认的Servlet和jsp代码模板
    使用js加载器动态加载外部Javascript文件
    JavaScript获取浏览器类型与版本
  • 原文地址:https://www.cnblogs.com/CtrlKismet/p/7181998.html
Copyright © 2020-2023  润新知