HDU5977 Garden of Eden 树分治+高维前缀和

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5977

题意:给一个有n(1<=n<=5e4)个节点的树,每个节点有一个颜色,共有k(1<=k<=7)种不同的颜色,问有多少个点对(u,v)(注意(u,v)和(v,u)算作两个答案),这些点对之间的路径上有k个不同的颜色。

解法:树分治+高维前缀和,暴力枚举就超时了,但是只要知道高维前缀和以及枚举子集的相关知识,就能用O(k*(1<


//高维前缀和+树分治
#include 
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
const int maxm = 2e5+10;
struct edge{
    int v,next,w;
}E[maxm];
int head[maxn],edgecnt;
int n,vis[maxn],root;
LL ans;
void init(){
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    edgecnt=ans=0;
}
void add(int u,int v){
    E[edgecnt].v = v, E[edgecnt].next = head[u],head[u] = edgecnt++;
}
int mx[maxn],siz[maxn],col[maxn],mi,K,k;
LL cnt[maxn], cnt1[maxn];
void dfssize(int u, int fa){//处理子树的大小
    siz[u]=1;
    mx[u]=0;
    for(int i=head[u];~i;i=E[i].next){
        int v=E[i].v;
        if(v!=fa&&!vis[v]){
            dfssize(v, u);
            siz[u]+=siz[v];
            if(siz[v]>mx[u]) mx[u]=siz[v];
        }
    }
}
void dfsroot(int r, int u, int fa){//求重心
    if(siz[r]-siz[u]>mx[u]) mx[u]=siz[r]-siz[u];
    if(mx[u]


你可能感兴趣的:(ACM/ICPC高维前缀和,ACM/ICPC树分治)