UOJ #579. 树上的颜色
生活随笔
收集整理的這篇文章主要介紹了
UOJ #579. 树上的颜色
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【題目描述】:給出一棵有N個點的有根樹,結點編號為1,2,3,……,N,根結點編號為1,編號為i的結點涂上顏色Ci。現在有M個詢問,每個詢問要求求出以結點u為根的子樹上涂有此種顏色的結點個數不小于k的顏色個數有多少。
【輸入描述】:第一行包含兩個正整數N和M。第二行包含N個正整數,C1,C2,…,CN。接下來的N-1行每行有兩個正整數x和y,表示結點x和y有邊相連。再接下來的M行每行有兩個正整數u和k,表示一個詢問。
【輸出描述】:輸出M行,每行一個非負整數,對應每個詢問的答案。
【樣例輸入1】:4 1
1 2 3 4
1 2
2 3
3 4
1 1【樣例輸出1】:4【樣例輸入2】:8 5
1 2 2 3 3 2 3 3
1 2
1 5
2 3
2 4
5 6
5 7
5 8
1 2
1 3
1 4
2 3
5 3【樣例輸出2】:2
2
1
0
1【時間限制、數據范圍及描述】:時間:1s 空間:256M對于10%的數據,N≤100,M≤100,Ci≤100;對于30%的數據,N≤500,M≤100;對于60%的數據,N≤2000,M≤100000;對于100%的數據,N≤100000,M≤100000,Ci≤100000。本題用color[i]統計第i鐘顏色的數量,用sum[i]統計顏色數量為i,i+1,i+2,……的顏色個數。
設要加入一個點,其顏色為x,則sum[color[x]+1]增加1,sum的其他值不變,同時color[x]++即可。同理,刪去一個點,sum[color[x]–]–即可。這時sum就是最終答案。
然而這時時間復雜度是O(N^2)的,還需進一步優化,于是看到區間修改和統計我們想到了莫隊.
但這里要更復雜一些,因為是在樹上,所以需要用樹上莫隊,將樹上的點按照dfs序拉成一個序列,再用莫隊即可求解。Code:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
const int N=100005;
int n,m,block,cnt,c[N],s[N],t[N],dfn,re[N],colour[N],num[N],sum[N],ans[N],head[N];
struct Node{int u,v,nxt;
}edge[N*2];
struct node{int l,r,k,id;
}q[N];
void Push(int u,int v){++cnt;edge[cnt].u=u;edge[cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
void dfs(int u,int fa){s[u]=++dfn;c[dfn]=colour[u];for (int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==fa){continue;}dfs(v,u);}t[u]=dfn;
}
bool cmp(node a,node b){return (a.l/block)^(b.l/block)?a.l<b.l:(((a.l/block)&1)?a.r<b.r:a.r>b.r);
}
int main(){int x,y,u,k;scanf("%d%d",&n,&m);block=sqrt(n);for(int i=1;i<=n;i++){scanf("%d",&colour[i]);}for(int i=1;i<n;i++){scanf("%d%d",&x,&y);Push(x,y);Push(y,x);}dfs(1,0);for(int i=1;i<=m;i++){scanf("%d%d",&u,&k);q[i]=(node){s[u],t[u],k,i};}sort(q+1,q+1+m,cmp);int L=1,R=0;for(int i=1;i<=m;i++){while(q[i].l<L){L--,num[c[L]]++,sum[num[c[L]]]++;}while(q[i].l>L){sum[num[c[L]]]--,num[c[L]]--,L++;}while(q[i].r>R){R++,num[c[R]]++,sum[num[c[R]]]++;}while(q[i].r<R){sum[num[c[R]]]--,num[c[R]]--,R--;}ans[q[i].id]=sum[q[i].k];}for(int i=1;i<=m;i++){printf("%d\n",ans[i]);}return 0;
}
轉載于:https://www.cnblogs.com/ukcxrtjr/p/11522098.html
總結
以上是生活随笔為你收集整理的UOJ #579. 树上的颜色的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P2827 蚯蚓
- 下一篇: UOJ #584. 天天去哪吃