codeforces1467 E. Distinctive Roots in a Tree(树上差分)
E. Distinctive Roots in a Tree
樹上差分
-
如果當(dāng)前節(jié)點(diǎn)u的某一棵子樹中的某個節(jié)點(diǎn)的值和當(dāng)前節(jié)點(diǎn)相同,那么除了當(dāng)前節(jié)點(diǎn)這一棵子樹節(jié)點(diǎn),其他節(jié)點(diǎn)(其他子樹以及u上面的節(jié)點(diǎn))一定不滿足要求。
-
如果當(dāng)前節(jié)點(diǎn)子樹之外的節(jié)點(diǎn)(u上面的節(jié)點(diǎn))與當(dāng)前節(jié)點(diǎn)值相同,那么當(dāng)前子樹節(jié)點(diǎn)不滿足要求。
如何知道當(dāng)前子樹中的節(jié)點(diǎn)是否與當(dāng)前節(jié)點(diǎn)相同?
dfs過程中記錄進(jìn)入該子樹之前某值的個數(shù)與出子樹后該值的個數(shù)進(jìn)行比較,如果比之前多,說明子樹中存在該值。
如何知道當(dāng)前節(jié)點(diǎn)所有子樹之外的節(jié)點(diǎn)是否存在與當(dāng)前值相同的節(jié)點(diǎn)?
如果不存在,說明當(dāng)前節(jié)點(diǎn)所有子樹出現(xiàn)該值個數(shù)和應(yīng)該與總個數(shù)相同
對于不能作為答案的節(jié)點(diǎn)標(biāo)記一下即可,由于只有子樹操作考慮dfs序,區(qū)間修改單點(diǎn)查詢差分即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<stack> #include<queue> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=200010,mod=1e9+7; int h[N],e[2*N],ne[2*N],idx; int a[N],cnt[N],num[N],s[N],n; map<int,int> mp; int find(int x) {if(!mp.count(x)) mp[x]=++idx;return mp[x]; } void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void update(int l,int r,int x) {s[l]+=x,s[r+1]-=x; } int dfn[N],timestamp,sz[N]; void dfs(int u,int fa) {dfn[u]=++timestamp;sz[u]=1;int now=cnt[a[u]];// 差分統(tǒng)計(jì)u子樹出現(xiàn)a[u]的次數(shù)cnt[a[u]]++;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;int pre=cnt[a[u]];//進(jìn)入子樹前dfs(j,u);sz[u]+=sz[j];if(cnt[a[u]]>pre) //說明j子樹出現(xiàn)了a[u]update(1,n,1),update(dfn[j],dfn[j]+sz[j]-1,-1);}if(cnt[a[u]]-now!=num[a[u]])//差分統(tǒng)計(jì)u子樹出現(xiàn)a[u]的次數(shù) 不等于總個數(shù)update(dfn[u],dfn[u]+sz[u]-1,1);//1表示不能作為答案} int main() {IO;int T=1;//cin>>T;while(T--){memset(h,-1,sizeof h);cin>>n;for(int i=1;i<=n;i++) {cin>>a[i];a[i]=find(a[i]);num[a[i]]++;//總個數(shù)}idx=0;for(int i=1;i<n;i++){int a,b;cin>>a>>b;add(a,b),add(b,a);}dfs(1,-1);int res=0;for(int i=1;i<=n;i++){s[i]+=s[i-1];if(!s[i]) res++;}cout<<res<<'\n';}return 0; }要加油哦~
總結(jié)
以上是生活随笔為你收集整理的codeforces1467 E. Distinctive Roots in a Tree(树上差分)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: codeforces1472 G. Mo
- 下一篇: codeforces1473 E.Min