CodeForces 620E"New Year Tree"(DFS序+線段樹+狀態壓縮)

 

傳送門c++

 

•題意

  給你一顆 n 個節點的樹,每一個節點被染上了顏色;ide

  有 m 次操做,每次操做的類型有兩種ui

    • 1 v c : 將以 v 爲根的子樹的結點所有塗成 c
    • 2 v : 詢問以 v 爲根的子樹的結點中不一樣顏色的數量

•題解

  由於操做的是某個節點對應的子樹,因此咱們能夠經過DFS序得到每個結點的子樹區間。spa

  以後咱們就將這個樹形的問題轉化成了一個線性區間的問題;code

  而後,就能夠用線段樹來維護(區間更新,區間查詢);blog

  求解某個區間不一樣顏色的個數要怎麼辦呢?ci

  剛開始,我在線段樹中定義了一個 $set$,存儲當前區間全部的顏色;get

  可是,用 $set$ 超時了;it

  由於總共的顏色最多隻有 60 種;event

  所以咱們能夠用一個範圍在 $long long$ 內的二進制數 $bit$ 存儲每一種顏色;

  ($bit$ 的二進制下的每一位表明着一種顏色)

•Code

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define ls(x) (x<<1)
  5 #define rs(x) (x<<1|1)
  6 #define mem(a,b) memset(a,b,sizeof(a))
  7 #define popcount(x) __builtin_popcountll(x)///獲取x的二進制位1的個數
  8 const int maxn=4e5+50;
  9 
 10 int n,m;
 11 int a[maxn];
 12 int num;
 13 int head[maxn];
 14 struct Edge
 15 {
 16     int to;
 17     int next;
 18 }G[maxn<<1];
 19 void addEdge(int u,int v)
 20 {
 21     G[num]={v,head[u]};
 22     head[u]=num++;
 23 }
 24 struct Seg
 25 {
 26     int l,r;
 27     ll sum;
 28     int lazy;
 29     int mid(){return l+((r-l)>>1);};
 30     void Set(int col)
 31     {
 32         sum=1ll<<col;
 33         lazy=col;
 34     }
 35 }seg[maxn<<2];
 36 
 37 ///[s[u],e[u]]區間表示以u爲根節點的子樹的全部節點所在的區間
 38 int s[maxn];
 39 int e[maxn];
 40 vector<int >vs;
 41 void DFS(int u,int f)
 42 {
 43     vs.push_back(u);
 44     s[u]=vs.size()-1;
 45     for(int i=head[u];~i;i=G[i].next)
 46     {
 47         int v=G[i].to;
 48         if(v != f)
 49             DFS(v,u);
 50     }
 51     e[u]=vs.size()-1;
 52 }
 53 void pushUp(int pos)
 54 {
 55     seg[pos].sum=seg[ls(pos)].sum|seg[rs(pos)].sum;
 56 }
 57 void pushDown(int pos)
 58 {
 59     int &lazy=seg[pos].lazy;
 60     if(lazy == -1)
 61         return ;
 62 
 63     seg[ls(pos)].Set(lazy);
 64     seg[rs(pos)].Set(lazy);
 65 
 66     lazy=-1;
 67 }
 68 void build(int l,int r,int pos)
 69 {
 70     seg[pos]={l,r};
 71     seg[pos].lazy=-1;
 72 
 73     if(l == r)
 74     {
 75         seg[pos].sum=1ll<<a[vs[l]];
 76         return ;
 77     }
 78 
 79     int mid=seg[pos].mid();
 80     build(l,mid,ls(pos));
 81     build(mid+1,r,rs(pos));
 82 
 83     pushUp(pos);
 84 }
 85 void update(int pos,int l,int r,int col)
 86 {
 87     if(seg[pos].l == l && seg[pos].r == r)
 88     {
 89         seg[pos].Set(col);
 90         return ;
 91     }
 92     pushDown(pos);
 93 
 94     int mid=seg[pos].mid();
 95     if(r <= mid)
 96         update(ls(pos),l,r,col);
 97     else if(l > mid)
 98         update(rs(pos),l,r,col);
 99     else
100     {
101         update(ls(pos),l,mid,col);
102         update(rs(pos),mid+1,r,col);
103     }
104     pushUp(pos);
105 }
106 ll query(int pos,int l,int r)
107 {
108     if(seg[pos].l == l && seg[pos].r == r)
109         return seg[pos].sum;
110     pushDown(pos);
111 
112     int mid=seg[pos].mid();
113     if(r <= mid)
114         return query(ls(pos),l,r);
115     else if(l > mid)
116         return query(rs(pos),l,r);
117     else
118         return query(ls(pos),l,mid)|query(rs(pos),mid+1,r);
119 }
120 void Solve()
121 {
122     vs.clear();
123     DFS(1,1);
124     build(0,vs.size()-1,1);
125 
126     while(m--)
127     {
128         int op;
129         scanf("%d",&op);
130         if(op == 1)
131         {
132             int v,c;
133             scanf("%d%d",&v,&c);
134             update(1,s[v],e[v],c);///更新v節點對應的子樹節點區間[s[v],e[v]]的顏色
135         }
136         else
137         {
138             int v;
139             scanf("%d",&v);
140             ll ans=query(1,s[v],e[v]);
141             printf("%d\n",popcount(ans));
142         }
143     }
144 }
145 void Init()
146 {
147     num=0;
148     mem(head,-1);
149 }
150 int main()
151 {
152 //    freopen("C:\\Users\\hyacinthLJP\\Desktop\\C++WorkSpace\\in&&out\\contest","r",stdin);
153     Init();
154     scanf("%d%d",&n,&m);
155     for(int i=1;i <= n;++i)
156         scanf("%d",a+i);
157     for(int i=1;i < n;++i)
158     {
159         int u,v;
160         scanf("%d%d",&u,&v);
161         addEdge(u,v);
162         addEdge(v,u);
163     }
164     Solve();
165 
166     return 0;
167 }
View Code
相關文章
相關標籤/搜索