博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【牛客Wannafly挑战赛12】小H和圣诞树
阅读量:5146 次
发布时间:2019-06-13

本文共 2780 字,大约阅读时间需要 9 分钟。

可以考虑边分治,对于某一种颜色,我们处理出分治边左右两边所有以这个颜色为端点的路径长度,之后随便拼一拼就好了

但是这样对于每一组询问都需要边分一遍,这样做复杂度是\(O(nm+n\log n)\)

还有一种更暴力的做法,就是枚举树上所有路径,这样就可以直接统计了,复杂度是\(O(n^2)\)

把这两个暴力结合一下,当一个分治块大小小于\(\sqrt{n}\)的时候,我们就直接跑第二种暴力,否则我们就跑边分治

跑第二种暴力的时候我们需要快速判断当前这个点对对应哪一个询问,于是需要二分一下,于是有一个\(\log\),所以我们把阈值设得比\(\sqrt{n}\)稍小一些,使得复杂度向边分治倾斜,这样就能跑过去了

代码

#include
#define re register#define LL long long#pragma GCC optimize(3)#define max(a,b) ((a)>(b)?(a):(b))inline int read() { char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;}const int maxn=1e5+5;const int M=4e5+3;int rn,n,num,rt,Mnow,S,B,tot,Q,sz;struct E{int v,nxt,w;}e[M<<1];std::vector
son[M],w[M];int vis[M],head[M],sum[M],col[maxn];LL Ans[maxn],tax[2][maxn],b[maxn];int st[2][M],top[2],t[2][maxn],c[maxn],qx[maxn],qy[maxn];inline int find(LL x) { int l=1,r=sz; while(l<=r) { int mid=l+r>>1; if(b[mid]==x) return mid; if(b[mid]
>1]) continue; getrt(e[i].v,x);sum[x]+=sum[e[i].v]; int now=max(sum[x],S-sum[x]); if(now
>1]) continue; dfs2(e[i].v,dis+e[i].w,x,o); }}void calc(int x,int fa,int o,LL dis) { if(x<=rn&&col[x]>=o) { int to=c[find(1ll*o*rn+col[x])]; if(to) Ans[to]+=dis; } for(re int i=head[x];i;i=e[i].nxt) { if(e[i].v==fa||vis[i>>1]) continue; calc(e[i].v,x,o,dis+e[i].w); }}void dfs(int x,int fa) { if(x<=rn) calc(x,0,col[x],0); for(re int i=head[x];i;i=e[i].nxt) { if(e[i].v==fa||vis[i>>1]) continue; dfs(e[i].v,x); }}void solve(int x,int s) { if(s<=B) {dfs(x,0);return;} Mnow=M,S=s,getrt(x,0); if(Mnow==M) return;vis[rt>>1]=1; dfs2(e[rt].v,e[rt].w,0,0);dfs2(e[rt^1].v,0,0,1); for(re int i=1;i<=Q;i++) { Ans[i]+=1ll*t[0][qx[i]]*tax[1][qy[i]]+1ll*t[1][qx[i]]*tax[0][qy[i]] +1ll*t[0][qy[i]]*tax[1][qx[i]]+1ll*t[1][qy[i]]*tax[0][qx[i]]; } while(top[0]) tax[0][st[0][top[0]]]=t[0][st[0][top[0]]]=0,top[0]--; while(top[1]) tax[1][st[1][top[1]]]=t[1][st[1][top[1]]]=0,top[1]--; int k=e[rt^1].v,h=S-sum[e[rt].v]; solve(e[rt].v,sum[e[rt].v]);solve(k,h);}int main() { rn=n=read(); for(re int i=1;i<=n;i++) col[i]=read(); for(re int x,y,z,i=1;i
qy[i]) std::swap(qx[i],qy[i]); b[i]=1ll*qx[i]*rn+qy[i]; } std::sort(b+1,b+Q+1);sz=std::unique(b+1,b+Q+1)-b-1; for(re int i=Q;i;--i) c[find(1ll*qx[i]*rn+qy[i])]=i; solve(1,n); for(re int i=1;i<=Q;i++) { int to=c[find(1ll*qx[i]*rn+qy[i])]; if(to!=i) {printf("%lld\n",Ans[to]);continue;} Ans[i]/=(qx[i]==qy[i]?2ll:1); printf("%lld\n",Ans[i]); } return 0;}

转载于:https://www.cnblogs.com/asuldb/p/11373650.html

你可能感兴趣的文章
spring IOC装配Bean(注解方式)
查看>>
[面试算法题]有序列表删除节点-leetcode学习之旅(4)
查看>>
SpringBoot系列五:SpringBoot错误处理(数据验证、处理错误页、全局异常)
查看>>
kubernetes_book
查看>>
OpenFire 的安装和配置
查看>>
侧边栏广告和回到顶部
查看>>
https://blog.csdn.net/u012106306/article/details/80760744
查看>>
ios应用版本号设置规则
查看>>
海上孤独的帆
查看>>
error: more than one device and emulator 问题解决
查看>>
springmvc集成Freemarke配置的几点
查看>>
Django 学习
查看>>
Linux-socket的close和shutdown区别及应用场景
查看>>
xpath
查看>>
parted分区
查看>>
图片标签img
查看>>
表哥的Access入门++以Excel视角快速学习数据库知识pdf
查看>>
TC 配置插件
查看>>
关于异步reset
查看>>
索引优先队列的工作原理与简易实现
查看>>