HDU 3974 Assign the task(dfs编号+线段树成段更新)

题意:给定点的上下级关系,规定如果给i分配任务a,那么他的所有下属。都停下手上的工作,开始做a。

操作 T x y 分配x任务y,C x询问x的当前任务;

Sample Input

 1
5
4 3
3 2
1 3
5 2
5
C 3
T 2 1
 C 3
T 3 2
C 3 

Sample Output

 Case #1:
-1
1
2 

思路:

利用dfs深度优先遍历重新编号,使一个结点的儿子连续。然后成段更新。

2:1-5

5:2-2

3:3-5

1:4-4

4:5-5

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50001
using namespace std;

int lazy[N<<2];
int task[N<<2];
int next[N],pre[N],to[N];
int uset[N];
int num;
int l[N],r[N];

int find_set(int x)
{
    while(uset[x]!=x)
        x=uset[x];
    return x;
}

void dfs(int root)
{
    int i=pre[root];
    l[root]=(++num);
    while(i!=-1)
    {
        dfs(to[i]);
        i=next[i];
    }
    r[root]=num;
}

void pushdown(int rt)
{
    if(lazy[rt]!=-1)
    {
        task[rt<<1]=lazy[rt];
        lazy[rt<<1]=lazy[rt];
        task[rt<<1|1]=lazy[rt];
        lazy[rt<<1|1]=lazy[rt];
        lazy[rt]=-1;
    }
}

void build(int l,int r,int rt)
{
    task[rt]=-1;
    lazy[rt]=-1;
    if(l==r)
        return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void update(int L,int R,int l,int r,int rt,int val)
{
    if(L<=l&&r<=R)
    {
        lazy[rt]=val;
        task[rt]=val;
        return;
    }
    pushdown(rt);
    int m=(r+l)>>1;
    if(L<=m) update(L,R,lson,val);
    if(R>m) update(L,R,rson,val);
}

void query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        printf("%d\n",task[rt]);
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m) query(L,R,lson);
    if(R>m) query(L,R,rson);
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        int n;
        int u,v;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            uset[i]=i;
            pre[i]=-1;
        }

        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            uset[u]=v;
            to[i]=u;
            next[i]=pre[v];
            pre[v]=i;

        }

        int root=find_set(1);
        num=0;

        dfs(root);
        //for(int i=1;i<=num;i++)
        //    printf("%d -- %d  %d\n",i,l[i],r[i]);
        //system("pause");

        build(1,num,1);
        int m;
        int a,b;
        char op[10];
        scanf("%d",&m);
        printf("Case #%d:\n",cas);
        for(int i=0;i<m;i++)
        {
            scanf("%s",&op);
            if(op[0]=='C')
            {
                scanf("%d",&a);
                query(l[a],l[a],1,num,1);
            }
            else
            {
                scanf("%d %d",&a,&b);
                update(l[a],r[a],1,num,1,b);
            }
        }
    }
    return 0;
}
时间: 2024-10-03 22:41:53

HDU 3974 Assign the task(dfs编号+线段树成段更新)的相关文章

HDU 3974 Assign the task(dfs时间戳+线段树成段更新)

题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: Sample Input 1 5 4 3 3 2 1 3 5 2 5 C 3 T 2 1 C 3 T 3 2 C 3 Sample Output Case #1: -1 1 2 思路: 利用dfs深度优先遍历又一次编号.使一个结点的儿子连续. 然后成段更新. 代码: #include<iostream> #include<cstdio

线段树(成段更新) HDU 1698 Just a Hook

题目传送门 1 /* 2 线段树-成段更新:第一题!只要更新区间,输出总长度就行了 3 虽然是超级裸题,但是用自己的风格写出来,还是很开心的:) 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <cmath> 8 #include <cstring> 9 #include <string> 10 #include <iostream> 11 using namesp

HDU 1698 Just a Hook (线段树 成段更新 lazy-tag思想)

题目链接 题意: n个挂钩,q次询问,每个挂钩可能的值为1 2 3,  初始值为1,每次询问 把从x到Y区间内的值改变为z.求最后的总的值. 分析:用val记录这一个区间的值,val == -1表示这个区间值不统一,而且已经向下更新了, val != -1表示这个区间值统一, 更新某个区间的时候只需要把这个区间分为几个区间更新就行了, 也就是只更新到需要更新的区间,不用向下更新每一个一直到底了,在更新的过程中如果遇到之前没有向下更新的, 就需要向下更新了,因为这个区间的值已经不统一了. 其实这就

线段树成段更新 hdu 1698 Just a Hook

题意:给出n根金属棒,和操作数q,初始时每个金属棒价值都为1,每次操作可以把从x到y的金属棒更换材质,铜为1,银为2,金为3,最后统计所有的金属棒总价值是多少. 线段树成段更新,需要用到lazy标记,所谓lazy标记就是:更新一个区间的时候不更新到底,只更新到第一个满足更新范围的区间(即范围内的最大的区间),然后给节点加上lazy标记,以后需要更新到该节点的子节点的时候,就把lazy标记转移到子节点上,这样大大提升了效率. 代码:

ZOJ1610_Count the Colors(线段树/成段更新)

解题报告 题意: 一根长度8000的线段上染色,求染完之后,每个颜色在线段上有多少个间断的区间. 思路: 区间问题用线段树,成段的更新区间,最后把所有的区间下压到叶子结点,统计叶子结点的颜色. #include <iostream> #include <cstring> #include <cstdio> using namespace std; int lz[32000],_hash[10000],color[10000],cnt; void push_down(in

POJ训练计划2528_Mayor&#39;s posters(线段树/成段更新+离散化)

解题报告 地址传送门 题意: 一些海报,覆盖上去后还能看到几张. 思路: 第一道离散化的题. 离散化的意思就是区间压缩然后映射. 给你这么几个区间[1,300000],[3,5],[6,10],[4,9] 区间左右坐标排序完就是 1,3,4,5,6,9,10,300000; 1,2,3,4,5,6, 7 ,8; 我们可以把上面的区间映射成[1,8],[2,4],[5,7],[3,6]; 这样就节省了很多空间. 给线段染色, lz标记颜色. #include <map> #include <

POJ训练计划2528_Mayor&amp;#39;s posters(线段树/成段更新+离散化)

解题报告 id=2528">地址传送门 题意: 一些海报,覆盖上去后还能看到几张. 思路: 第一道离散化的题. 离散化的意思就是区间压缩然后映射. 给你这么几个区间[1,300000],[3,5],[6,10],[4,9] 区间左右坐标排序完就是 1,3,4,5,6,9,10,300000; 1,2,3,4,5,6, 7 ,8; 我们能够把上面的区间映射成[1,8],[2,4],[5,7],[3,6]; 这样就节省了非常多空间. 给线段染色, lz标记颜色. #include <ma

POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新

题目来源:POJ 2763 Housewife Wind 题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x 思路:树上两点u, v距离为d[u]+d[v]-2*d[LCA(u,v)] 现在d数组是变化的 对应每一条边的变化 他修改的是一个区间 用时间戳处理每个点管辖的区域 然后用线段树修改 线段树的叶子节点村的是根到每一个点的距离 求最近公共祖先没差别 只是堕落用线段树维护d数组 各种错误 4个小时 伤不起 #include <cs

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>