[JZOJ5058]采蘑菇
来源:互联网 发布:php 记录日志 编辑:程序博客网 时间:2024/04/28 09:54
题目大意
给定一棵
对于每一个点
题目分治
首先这题虚树肯定可以做,这里不讲。
考虑使用点分治,先不考虑有多种颜色。假设我只想统计出现过某一种颜色的路径总数。
对于分治重心
现在考虑将其扩展到多种颜色上。
对于分治重心
时间复杂度
代码实现
#include <iostream>#include <cstdio>#include <cctype>using namespace std;typedef long long LL;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar(); while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}int buf[30];void write(LL x){ if (x<0) putchar('-'),x=-x; for (;x;x/=10) buf[++buf[0]]=x%10; if (!buf[0]) buf[++buf[0]]=0; for (;buf[0];putchar('0'+buf[buf[0]--]));}const int N=300050;const int E=N<<1;int last[N],fa[N],size[N],col[N],f[N],ext[N],que[N];int nxt[E],tov[E];bool vis[N];LL ans[N];int n,tot,head,tail,cur;LL sum;void insert(int x,int y){tov[++tot]=y,nxt[tot]=last[x],last[x]=tot;}int core(int og){ int i,x,y,ret,rets=n,tmp; for (head=0,fa[que[tail=1]=og]=0;head<tail;) for (size[x=que[++head]]=1,i=last[x];i;i=nxt[i]) if ((y=tov[i])!=fa[x]&&!vis[y]) fa[que[++tail]=y]=x; for (head=tail;head>1;--head) size[fa[que[head]]]+=size[que[head]]; for (head=1;head<=tail;++head) { for (tmp=size[og]-size[x=que[head]],i=last[x];i;i=nxt[i]) if ((y=tov[i])!=fa[x]&&!vis[y]) tmp=max(tmp,size[y]); if (tmp<rets) ret=x,rets=tmp; } return ret;}void dfs(int x){ size[x]=1; for (int i=last[x],y;i;i=nxt[i]) if ((y=tov[i])!=fa[x]&&!vis[y]) fa[y]=x,dfs(y),size[x]+=size[y];}void count(int x,int *f,int sig){ if (!ext[col[x]]++) f[col[x]]+=sig*size[x],sum+=sig*size[x],++cur; for (int i=last[x],y;i;i=nxt[i]) if ((y=tov[i])!=fa[x]&&!vis[y]) count(y,f,sig); if (!--ext[col[x]]) --cur;}void calc(int x,int siz,int c){ if (!ext[col[x]]++) sum-=f[col[x]],++cur; ans[x]+=1ll*siz*cur+sum,ans[c]+=cur; for (int i=last[x],y;i;i=nxt[i]) if ((y=tov[i])!=fa[x]&&!vis[y]) calc(y,siz,c); if (!--ext[col[x]]) sum+=f[col[x]],--cur;}void solve(int x){ int c=core(x); ++ans[c],size[c]=1; for (int i=last[c],y;i;i=nxt[i]) if (!vis[y=tov[i]]) fa[y]=c,dfs(y),size[c]+=size[y]; for (int i=last[c],y;i;i=nxt[i]) if (!vis[y=tov[i]]) count(y,f,1); for (int i=last[c],y;i;i=nxt[i]) if (!vis[y=tov[i]]) count(y,f,-1),++ext[col[c]],sum-=f[col[c]],cur=1,calc(y,size[c]-size[y],c),--ext[col[c]],sum+=f[col[c]],cur=0,count(y,f,1); for (int i=last[c],y;i;i=nxt[i]) if (!vis[y=tov[i]]) count(y,f,-1); vis[c]=1; for (int i=last[c],y;i;i=nxt[i]) if (!vis[y=tov[i]]) solve(y);}int main(){ freopen("mushroom.in","r",stdin),freopen("mushroom.out","w",stdout); n=read(); for (int i=1;i<=n;++i) col[i]=read(); for (int i=1,x,y;i<n;++i) x=read(),y=read(),insert(x,y),insert(y,x); solve(1); for (int i=1;i<=n;++i) write(ans[i]),putchar('\n'); fclose(stdin),fclose(stdout); return 0;}
0 0
- [JZOJ5058]采蘑菇
- 【JZOJ5058】【GDSOI2017模拟4.13】采蘑菇
- 采蘑菇
- 采蘑菇
- 洛谷2656 采蘑菇
- 洛谷 P2656 采蘑菇
- 【洛谷 P2656】采蘑菇
- 洛谷2656 采蘑菇
- 洛谷P2656 采蘑菇
- qduoj GZS采蘑菇
- 洛谷 P2656 采蘑菇
- 【洛谷 2656】采蘑菇
- 洛谷P2656 采蘑菇
- 洛谷P2656 采蘑菇
- 【洛谷 P2656】采蘑菇
- BOJ 478 小妹妹采蘑菇
- boj478. 小妹妹采蘑菇-概率
- c++游戏设计四:采蘑菇
- win10 安装 Cygwin
- Dubbo与Zookeeper、Spring整合使用
- webview相关知识
- 在QT集成开发环境中用OpenCV读取一张图片并显示
- MySQL导入导出liunx
- [JZOJ5058]采蘑菇
- MVC使用ajax方法提交表单(一)
- Ubuntu16.04编译安装OpenCV3.20
- 删除孩子DOM节点
- Linux系统操作指令-centos
- 带你搞懂朴素贝叶斯分类算法
- HDU1556
- [kuangbin带你飞]专题一 简单搜索 K题迷宫
- Nginx 配置实现web解析php代码 过程记录