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>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define read_ freopen("i.txt","r",stdin)
using  namespace std;
const int N=50010;

int task[N<<2],lazy[N<<2];
struct node{
        int to,next;
}edge[N];

int ll;
int l[N],r[N];
int uset[N],adj[N];
int num;
void addedge(int u,int v)
{
        edge[ll].to=u;
        edge[ll].next=adj[v];
        adj[v]=ll++;
}

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

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

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

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

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

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()
{
        //read_;
        int T;
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++)
        {
                int n;
                scanf("%d",&n);
                ll=0;
                num=0;
                for(int i=0;i<=n;i++)
                {
                        adj[i]=-1;
                        uset[i]=i;
                }
                int u,v;
                for(int i=1;i<n;i++)
                {
                        scanf("%d%d",&u,&v);
                        uset[u]=v;
                        addedge(u,v);
                }
                int root=find_set(1);
                dfs(root);
                build_tree(1,num,1);
                int m;
                scanf("%d",&m);
                char op[5];
                int a,b;
                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],b,1,num,1);
                        }
                }
        }
        return 0;
}
时间: 2024-10-17 07:48:31

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

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

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<iostr

线段树(成段更新) 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

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>