• Assign the task---hdu3974(线段树优化+dfs)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3974

    题意就是:公司有n个员工,关系有n-1个,T x y 代表把工作y交给员工x;

    员工可以把工作交给下属;

    本来是线段树的题,但是我真心看不懂,所以就找了个能看懂的方法了

     

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define N 50050
    
    int f[N];
    struct node
    {
        int task, order;
    }a[N];
    int Query(int x)
    {
        int order = -1, ans = -1;
        while(x != 0)
        {
            if(a[x].order > order)
            {
                ans = a[x].task;
                order = a[x].order;
            }
            x = f[x];
        }
        return ans;
    }
    
    int main()
    {
        int T, n, m, t=1, x, y;
        char s[10];
        scanf("%d", &T);
        while(T--)
        {
    
            scanf("%d", &n);
            memset(a, -1, sizeof(a));
            memset(f, 0, sizeof(f));
            for(int i=1; i<=n-1; i++)
            {
                scanf("%d %d", &x, &y);
                f[x] = y;
            }
            scanf("%d", &m);
            printf("Case #%d:
    ", t++);
            for(int i=1; i<=m; i++)
            {
                scanf("%s", s);
                if(s[0] == 'C')
                {
                    scanf("%d", &x);
                    printf("%d
    ", Query(x));
                }
                else
                {
                    scanf("%d %d", &x, &y);
                    a[x].order = i;//工作的顺序;
                    a[x].task = y;
                }
            }
        }
        return 0;
    }
    View Code

     看了学长的代码,有点理解了,就写了一下;

    补充一下线段树的方法吧

    可以用每个节点的所包含的子节点段来当做线段树的节点,查找每个节点所包含的段可以用简单的DFS实现。

     

    #include<stdio.h>
    #include<vector>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #define N 50050
    #define Lson r<<1
    #define Rson r<<1|1
    #define INF 0xfffffff
    using namespace std;
    
    int s[N], e[N], used[N], index;//s表示每个员工所有下属的开始和结束节点,包含本身
    vector<int>G[N];
    
    struct SegTree
    {
        int L, R, task, vis;
        int mid()
        {
            return (L+R)>>1;
        }
        int len()
        {
            return R-L+1;
        }
    }a[N<<2];
    void dfs(int k)
    {
        s[k]=++index;
        for(int i=0,len=G[k].size(); i<len; i++)
            dfs(G[k][i]);
        e[k]=index;
    }
    void BuildTree(int r, int L, int R)
    {
        a[r].L =  L; a[r].R = R;
        a[r].task = -1; a[r].vis = 0;
        if(L == R)return ;
    
        BuildTree(Lson, L, a[r].mid());
        BuildTree(Rson, a[r].mid()+1,R);
    }
    void Down(int r)
    {
        if(a[r].L != a[r].R && a[r].vis == 1)
        {
            a[Lson].vis = a[Rson].vis = 1;
            a[Lson].task = a[Rson].task = a[r].task;
            a[r].vis = 0;
        }
    }
    void Update(int r, int L, int R, int k)
    {
        Down(r);
        if(a[r].L == L && a[r].R == R)
        {
            a[r].task = k;
            a[r].vis = 1;
            return;
        }
    
        if(R <= a[r].mid())
            Update(Lson, L, R, k);
        else if(L > a[r].mid())
            Update(Rson, L, R, k);
        else
        {
            Update(Lson, L, a[r].mid(), k);
            Update(Rson, a[r].mid()+1, R, k);
        }
    }
    int Query(int r, int k)
    {
        Down(r);
        if(a[r].L == a[r].R)
            return a[r].task;
        if(k<=a[r].mid())
            return Query(Lson, k);
        else
            return Query(Rson, k);
    }
    int main()
    {
        int T, t=1, n, m, x, y, u, v;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            memset(used, 0, sizeof(used));
            for(int i=0;i<=n;i++)
                G[i].clear();
            for(int i=1; i<n; i++)
            {
                scanf("%d %d", &u, &v);
                G[v].push_back(u);
                used[u] = 1;
            }
            index = 0;
            for(int i=1; i<=n; i++)
            {
                if(used[i]==0)
                {
                    dfs(i);break;
                }
            }
            BuildTree(1, 1, n);
            printf("Case #%d:
    ", t++);
            scanf("%d", &m);
            while(m--)
            {
                char str[5];
                scanf("%s", str);
                if(str[0]=='C')
                {
                    scanf("%d", &x);
                    printf("%d
    ", Query(1,s[x]));
                }
                else
                {
                    scanf("%d%d", &x, &y);
                    Update(1, s[x], e[x], y);
                }
            }
        }
        return 0;
    }
    View Code

     很久之后的今天20160505再来看这道题,完全不是很难看懂的状态了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    using namespace std;
    typedef long long LL;
    #define met(a, b) memset(a, b, sizeof(a))
    #define N 50011
    #define Lson r<<1
    #define Rson r<<1|1
    
    struct node
    {
        int L, R, task, flag;///flag表示此区间是否被全部覆盖,如果是那么task表示此区间的工作是什么;
        int Mid(){ return (L+R)/2; }
        int Len(){ return (R-L+1); }
    }a[N*4];
    
    vector<vector<int> >G;
    int s[N], e[N], du[N], Index;
    
    void dfs(int u)
    {
        s[u] = ++Index;///相当于是记录u得起始下属下标,结束下标在递归回来的时候确定的,
        int len = G[u].size();
        for(int i=0; i<len; i++)
            dfs(G[u][i]);
        e[u] = Index;
    }
    
    void Build(int r, int L, int R)
    {
        a[r].L = L, a[r].R = R; a[r].task = -1;
        if( L == R )return;
        Build(Lson, L, a[r].Mid());
        Build(Rson, a[r].Mid()+1, R);
    }
    
    void Down(int r)
    {
        if(a[r].flag && a[r].L != a[r].R)
        {
            a[Lson].flag = a[Rson].flag = a[r].flag;
            a[Lson].task = a[Rson].task = a[r].task;
            a[r].flag = 0;
        }
    }
    
    void Update(int r, int L, int R, int task)
    {
        if(a[r].L == L && a[r].R == R)
        {
            a[r].flag = 1;
            a[r].task = task;
            return ;
        }
        Down(r);
        if( R <= a[r].Mid() )
            Update(Lson, L, R, task);
        else if( L > a[r].Mid() )
            Update(Rson, L, R, task);
        else
        {
            Update(Lson, L, a[r].Mid(), task);
            Update(Rson, a[r].Mid()+1, R, task);
        }
    }
    int Query(int r, int pos)
    {
        Down(r);///因为上面也许没有更新到最底部,所以要再接着往下压;
    
        if(a[r].L == a[r].R)///找到叶子节点,并返回;
            return a[r].task;
    
        if(pos <= a[r].Mid())
            return Query(Lson, pos);
        else
            return Query(Rson, pos);
    }
    
    int main()
    {
        int T, n, m, u, v, x, y, t = 1;
        scanf("%d", &T);
        while(T--)
        {
            met(du, 0); met(s, 0); met(e, 0);
    
            scanf("%d", &n);
    
            G.clear();
            G.resize(n+5);
    
            for(int i=1; i<n; i++)
            {
                scanf("%d %d", &u, &v);
                G[v].push_back(u);
                du[u] = 1;
            }
            Index = 0;
            for(int i=1; i<=n; i++)
            {
                if(!du[i])///找到根节点,然后按照递归的形式找到自己连续的下属;
                {
                    dfs(i);break;
                }
            }
            Build(1, 1, n);
            scanf("%d", &m);
            printf("Case #%d:
    ", t++);
            while(m--)
            {
                char ch[15];
                scanf("%s", ch);
                if(ch[0]=='T')
                {
                    scanf("%d %d", &x, &y);
                    Update(1, s[x], e[x], y);///更新的是x这个人的所有下属;
                }
                else
                {
                    scanf("%d", &x);
                    printf("%d
    ", Query(1, s[x]));
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    《程序员代码面试指南》第三章 二叉树问题 先序、中序和后序数组两两结合重构二叉树
    《程序员代码面试指南》第三章 二叉树问题 二叉树节点间的最大距离问题
    《程序员代码面试指南》第三章 二叉树问题 在二叉树中找到一个节点的后继节点
    《程序员代码面试指南》第三章 二叉树问题 通过有序数组生成搜索二叉树
    《程序员代码面试指南》第三章 二叉树问题 判断一个树是搜索二叉树和完全二叉树
    《程序员代码面试指南》第三章 二叉树问题 根据后序数组重建搜素二叉树
    《程序员代码面试指南》第三章 二叉树问题 判断二叉树是否为搜素二叉树
    博弈知识入门引导
    ZZNUOJ-2157: 水滴来袭-【干扰阅读-卡模糊精度1e-8的问题】
    ZZNUOJ-2155-单身man集合-【标程做法:数位DP-1-10^8,提前暴力打表法: 砍时间复杂度到10^5】
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4694429.html
Copyright © 2020-2023  润新知