题意:问你每条边,在只有这个边不考虑的情况下,两个数共有颜色的数目。
解:
可以转化为 dfs许的情况下,求一段区间的的颜色数目和一段区间独有的颜色数目。
1、求一段区间的颜色数目是一个经典题目,拓展还有求一段区间每一个颜色最多贡献k的情况下有多少个这种题目
(1)利用主席树求 pre[i]值小于l的点有多少个
(2)这一部分也可以用树状数组统计出来, 也是对询问的右端点排序然后,我们没看到一个点先删掉前面的影响,
for(int i=1,j=1;i<n;i++){
while(j<=que[i].r){
if(pre[a[vis[j]]]){
add_t(pre[a[vis[j]]],-1);
}
pre[a[vis[j]]]=j;
add_t(j,1);
j+=1;
}
ans[que[i].ind]=ask_t(que[i].r)-ask_t(que[i].l-1);
}
2、求区间内独有颜色的数目?
(1)首先预处理出来,每个颜色 最左L[i]最右R[i]
(2)每一个子树相当于一个区间询问,那么对于这些询问对有锻炼que[i].r进行排序(升)
(3)没到一个R[i],就就在树状数组中插入让的L[i],我们每一个询问问的 大于等于que[i].l的点有多少个、
主席树代码
#include <bits/stdc++.h>
#define en '\n'
#define Swt signed main
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxm=(1e5+10)*77;
int tot;
struct node{
int v,nxt,w;
}edge[maxn<<1];
int rd(){int tem;scanf("%d",&tem);return tem;}
int head[maxn];
void add(int x,int y,int w){edge[++tot]=(node){y,head[x],w};head[x]=tot;}
int col[maxn],dfn,in_ind[maxn],out_ind[maxn],in_edge[maxn],col_sum[maxn],c[maxn],vis[maxn],a[maxn];
int R[maxn],L[maxn],pre[maxn];
int col_have[maxn],rt[maxn];
int sm[maxm],ls[maxm],rs[maxm];
void dfs(int x,int f,int from){
in_ind[x]=++dfn;
vis[dfn]=x;
in_edge[x]=from;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].v;if(y==f)continue;
dfs(y,x,edge[i].w);
}
out_ind[x]=dfn;
}
void update(int &x,int y,int l,int r,int pos){
x=++tot;
sm[x]=sm[y];ls[x]=ls[y],rs[x]=rs[y];
sm[x]+=1;
if(l==r)return ;
int mid=(l+r)>>1;
if(pos<=mid)update(ls[x],ls[y],l,mid,pos);
else update(rs[x],rs[y],mid+1,r,pos);
}
int ask(int x,int y,int l,int r,int ql,int qr){
if(ql<=l and r<=qr)return sm[y]-sm[x];
int mid=(l+r)>>1;
int tem=0;
if(ql<=mid)tem+=ask(ls[x],ls[y],l,mid,ql,qr);
if(qr>mid)tem+=ask(rs[x],rs[y],mid+1,r,ql,qr);
return tem;
}
#define lowbit(x) (x&(-x))
void add_t(int x,int val){
for(;x<maxn-1;x+=lowbit(x)){
c[x]+=val;
}
}
int ask_t(int x){int res=0; for(;x;x-=lowbit(x))res+=c[x]; return res;}
int que[maxn];
void dfs_2(int x,int f){
if(R[a[x]]==in_ind[x]){
add_t(L[a[x]],1);
}
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].v;if(y==f)continue;
dfs_2(y,x);
}
col_have[x]-=ask_t(maxn-3)-ask_t(in_ind[x]-1);
//cout<<x<<' '<<col_have[x]<<en;
que[in_edge[x]]=col_have[x];
}
Swt(){
#ifdef local
freopen("input2.txt","r",stdin);
#endif // local
int n=rd();
for(int i=1;i<=n;i++){a[i]=rd();col_sum[a[i]]+=1;}
for(int i=1;i<n;i++){int x=rd(),y=rd();add(x,y,i);add(y,x,i);}
dfs(1,0,0);
for(int i=1;i<=n;i++){/// i is dfs_index
int ind=vis[i];
pre[i]=col[a[ind]];col[a[ind]]=i;
if(L[a[ind]]==0)L[a[ind]]=i;
R[a[ind]]=i;
}
for(int i=1;i<=n;i++){update(rt[i],rt[i-1],0,n,pre[i]);}
for(int i=1;i<=n;i++){
col_have[i]=ask(rt[in_ind[i]-1],rt[out_ind[i]],0,n,0,in_ind[i]-1);
}
dfs_2(1,0);
for(int i=1;i<n;i++){
cout<<que[i]<<'\n';
}
return 0;
}
两个树状数组代码
#include <bits/stdc++.h>
#define en '\n'
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int tot;
struct node{
int v,nxt,w;
}edge[maxn<<1];
int rd(){int tem;scanf("%d",&tem);return tem;}
int head[maxn];
void add(int x,int y,int w){edge[++tot]=(node){y,head[x],w};head[x]=tot;}
int dfn,in_ind[maxn],out_ind[maxn],c[maxn],c2[maxn],vis[maxn],a[maxn];
int R[maxn],L[maxn],pre[maxn],ans[maxn];
struct nodee{
int l,r,ind;
}que[maxn];
void dfs(int x,int f,int from){
in_ind[x]=++dfn;
if(!L[a[x]])L[a[x]]=dfn;
R[a[x]]=dfn;
que[from].l=dfn;
vis[dfn]=x;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].v;if(y==f)continue;
dfs(y,x,edge[i].w);
}
out_ind[x]=dfn;
que[from].r=dfn;
}
#define lowbit(x) (x&(-x))
void add_t2(int x,int val){
x+=1;
for(;x<maxn-1;x+=lowbit(x)){
c2[x]+=val;
}
}
int ask_t2(int x){
x+=1;
int res=0;
for(;x;x-=lowbit(x)){
res+=c2[x];
}return res;
}
void add_t(int x,int val){
for(;x<maxn-1;x+=lowbit(x)){
c[x]+=val;
}
}
int ask_t(int x){int res=0; for(;x;x-=lowbit(x))res+=c[x];return res;}
void dfs_2(int x,int f,int from){
if(R[a[x]]==in_ind[x]){
add_t2(L[a[x]],1);
}
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].v;if(y==f)continue;
dfs_2(y,x,edge[i].w);
}
ans[from]-=ask_t2(maxn-3)-ask_t2(in_ind[x]-1);
}
bool cmp(nodee a,nodee b){
return a.r<b.r;
}
signed main(){
#ifdef local
freopen("input2.txt","r",stdin);
#endif // local
int n=rd();
for(int i=1;i<=n;i++){a[i]=rd();}
for(int i=1;i<=n;i++)que[i].ind=i;
for(int i=1;i<n;i++){int x=rd(),y=rd();add(x,y,i);add(y,x,i);}
dfs(1,0,0);
//cout<<'s';return 0;
sort(que+1,que+n,cmp);
// cout<<'s';return 0;
for(int i=1,j=1;i<n;i++){
while(j<=que[i].r){
if(pre[a[vis[j]]]){
add_t(pre[a[vis[j]]],-1);
}
pre[a[vis[j]]]=j;
add_t(j,1);
j+=1;
}
ans[que[i].ind]=ask_t(que[i].r)-ask_t(que[i].l-1);
}
//cout<<'s';return 0;
dfs_2(1,0,0);
for(int i=1;i<n;i++){
cout<<ans[i]<<en;
}
return 0;
}