码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 6 E dfs序+线段树

时间:2016-11-04 14:18:44      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:记录   space   void   include   ret   stdio.h   ack   ati   vector   

题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色

比较容易想到dfs序+线段树去做

dfs序是很久以前看的bilibili上电子科技大学发的视频学习的 将一颗树通过dfs编号的方式 使每个点的子树的编号连在一起作为相连的区间 就可以配合线段树搞子树

因为以前好像听说过 线段树可以解决一种区间修改和查询区间中不同的xx个数...所以一下子就想到了...

但是我不会写线段树..只会最简单的单点修改区间查询...不会用延迟标记...所以拿出书现学了一发..

问学长怎么记录不同的颜色个数 学长就机智的告诉了我用longlong来搞..

虽然知道了思路..还是写了一天多..

dfs序 做出每个点的编号 并且记录每个点的子树的编号的左右区间 

初始进行crea的时候 进行赋值并且pushup

利用longlong的64位来存有哪种颜色 利用或来做转移

1L<<50 什么的 好像左移过了多少就崩了..要在外边定义L的变量..哭..

写线段树好累...(脸上挂满泪痕)...不过桃桃的小粉红敲起来好舒服...

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
#define L long long
int n , m ;
struct node{
    int l,r;
    L ma;
};
int a[400050];
node tree[400050*8];
vector<int >q[400050];
int id[400050];
L mark[400050*8];
int cnt ;
struct no{
    int l,r;
};
no zg[400050];
int fx[400050];
void dfs(int u){
    id[u] = ++cnt;
    fx[cnt] = u;
    zg[u].l = cnt;
    for(int i=0;i<q[u].size();i++){
        int v = q[u][i];
        if(id[v] == -1){
           dfs(v);
        }
    }
    zg[u].r = cnt;
}
void pushup(int root){
    tree[root].ma = tree[root*2].ma | tree[root*2+1].ma;
}
void pushdown(int root){
    if(mark[root] != -1){
        mark[root*2] = mark[root*2+1] = mark[root];
        tree[root].ma = mark[root];
        tree[root*2].ma = tree[root*2+1].ma = mark[root];
        mark[root] = -1;
    }
}
void crea(int root ,int l,int r){
    tree[root].l = l;
    tree[root].r = r;
    if(l == r){
        L res = 1;
        res <<= a[fx[l]];
        tree[root].ma = (res);
        return ;
    }
    int m = (l + r) >> 1;
    crea(root*2,l,m);
    crea(root*2+1,m+1,r);
    pushup(root);
}
void upda(int root , int l , int r ,int c){
    if(tree[root].r < l || tree[root].l > r){
        return ;
    }
    if(tree[root].r <= r && tree[root].l >= l){
        L res = 1;
        res <<= c;
        mark[root] = (res);
        pushdown(root);
        return ;
    }
    pushdown(root);
    upda(root*2,l,r,c);
    upda(root*2+1,l,r,c);
    pushup(root);
}
L query(int root ,int l , int r){
    pushdown(root);
    if(tree[root].r < l || tree[root].l > r){
        return 0;
    }
    if(tree[root].r <= r && tree[root].l >= l){
        return tree[root].ma;
    }
    L ans = 0;
    ans |= query(root*2,l,r);
    ans |= query(root*2+1,l,r);
    pushup(root);
    return ans ;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        q[i].clear();
    }
    cnt = 0;
    memset(id,-1,sizeof(id));
    for(int i=1;i<=n-1;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        q[v].push_back(u);
        q[u].push_back(v);
    }
    memset(mark,-1,sizeof(mark));
    dfs(1);
    crea(1,1,cnt);
    for(int i=1;i<=m;i++){
        int k ;
        scanf("%d",&k);
        if(k == 1){
            int v,c;
            scanf("%d%d",&v,&c);
            int ll = zg[v].l;
            int rr = zg[v].r;
            upda(1,ll,rr,c);
        }
        else {
            int v;
            scanf("%d",&v);
            int ll = zg[v].l;
            int rr = zg[v].r;
            L res = query(1,ll,rr);
            int ans = 0;
            while(res > 0){
                ans += (res %2);
                res >>= 1;
            }
            printf("%d\n",ans);
        }
    }
}

  

Educational Codeforces Round 6 E dfs序+线段树

标签:记录   space   void   include   ret   stdio.h   ack   ati   vector   

原文地址:http://www.cnblogs.com/rayrayrainrain/p/6029779.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!