bzoj 3631 [JLOI2014]松鼠的新家
来源:互联网 发布:java 开发就业班 编辑:程序博客网 时间:2024/04/19 17:05
题目
传送门
题解
看到某Yuta的树总结觉得LCA+树上差分挺好写而且差分没写过准备水一发结果水了一上午qwq。因为第一次写树上差分和树剖求LCA,结果树剖版子某处打错了。。(而且差分点和差分边还是有一定区别的)。
这题可以用树剖水部分分,不过n有30w,log方就会被卡了。所以利用差分思想把区间修改转化为点修改。给每个点一个tag表示新增值(貌似怪怪的)。如果有条路径(i,j)需要标记那么进行如下操作
tag(i)++;tag(j)++;tag(LCA(i,j))- -;tag(father(LCA(i,j)))- -;
这样能够达到标记经过的点的效果,请自行脑补如果是经过的边如何标记。
那么就把路径拆分就好了,但是这道题非起始端点会被多算一次(在衔接处),所以统计完后减回来。
题很水,人很蠢。
代码
//QWsin#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=600000+10;const int maxm=1200000+10;inline int read(){ int ret=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0'; return ret;}int to[maxn];int first[maxn],next[maxm],ecnt;struct Edge{int u,v;Edge(int u=0,int v=0):u(u),v(v){}}e[maxm];inline void add_edge(int u,int v){ next[ecnt]=first[u];first[u]=ecnt;e[ecnt++]=Edge(u,v); next[ecnt]=first[v];first[v]=ecnt;e[ecnt++]=Edge(v,u);}int top[maxn],hv[maxn],sz[maxn],p[maxn],dep[maxn];int tag[maxn]; int dfs1(int u,int fa,int deep=1){ p[u]=fa;dep[u]=deep;sz[u]=1;int msz=0; for(int i=first[u];i!=-1;i=next[i]) if(e[i].v!=fa){ int lch=dfs1(e[i].v,u,deep+1); if(lch > msz) msz=lch,hv[u]=e[i].v; sz[u]+=lch; } return sz[u];}void dfs2(int u,int Top){ top[u]=Top; if(sz[u]==1) return ; dfs2(hv[u],Top); for(int i=first[u];i!=-1;i=next[i]) if(e[i].v!=p[u]&&e[i].v!=hv[u]) dfs2(e[i].v,e[i].v);}int LCA(int a,int b){ for(;top[a]!=top[b];b=p[top[b]]) if(dep[top[a]] > dep[top[b]]) swap(a,b); return dep[a]<dep[b]?a:b;}int ans[maxn],sum,n;int dfs3(int cur){ int sum=tag[cur]; for(int i=first[cur];i!=-1;i=next[i]) if(e[i].v!=p[cur]) sum+=dfs3(e[i].v); if(to[1]!=cur) ans[cur]=sum-1; else ans[cur]=sum; return sum;}int main(){ n=read();memset(first,-1,sizeof(first)); for(int i=1;i<=n;i++) to[i]=read(); for(int i=1;i<n;i++) add_edge(read(),read()); int root=1; dfs1(root,root);dfs2(root,root); tag[to[1]]++;tag[to[2]]++; int lca=LCA(to[1],to[2]); tag[lca]--;if(lca!=root) tag[p[lca]]--; for(int i=2;i<n;i++) { int lca=LCA(to[i],to[i+1]); tag[to[i]]++;tag[to[i+1]]++; tag[lca]--;if(lca!=root) tag[p[lca]]--; } dfs3(root); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0;}
2 0
- bzoj 3631: [JLOI2014]松鼠的新家
- 【BZOJ 3631】 [JLOI2014]松鼠的新家
- bzoj 3631: [JLOI2014]松鼠的新家
- bzoj 3631 [JLOI2014]松鼠的新家
- BZOJ 3631 [JLOI2014]松鼠的新家
- bzoj 3631 [JLOI2014]松鼠的新家
- BZOJ JLOI2014 松鼠的新家
- BZOJ P3631[JLOI2014]松鼠的新家
- BZOJ 3631 JLOI2014 松鼠的新家 树链剖分/LCA
- BZOJ 3631 [JLOI2014]松鼠的新家 tarjanlca
- BZOJ 3631 [JLOI2014]松鼠的新家==树剖
- bzoj 3631: [JLOI2014]松鼠的新家 树链剖分
- 【bzoj 3631】[JLOI2014]松鼠的新家(树链剖分)
- Bzoj 3631: [JLOI2014]松鼠的新家(树链剖分+线段树)
- [BZOJ 3631][JLOI2014]松鼠的新家 dfs
- BZOJ 3631 [JLOI2014]松鼠的新家 树链剖分
- BZOJ 3631: [JLOI2014]松鼠的新家 树上差分
- BZOJ 3631: [JLOI2014]松鼠的新家【差分】【LCA】
- 实现windows和linux服务器之间文件共享,工具就是Samba软件中的一种,samba-client。
- 题目1107:搬水果【哈夫曼树模型】
- Storm Internal
- 存储过程-第一课
- JAVA调用SAP的函数RFC--个人小结
- bzoj 3631 [JLOI2014]松鼠的新家
- 朴素贝叶斯分类器的python实现
- 请解释&和&&、|和||的区别?
- 用 QT实现拖放(drag-drop)功能
- SCPPO(二十四):Server服务器安装Wifi
- DrawerLayout侧拉菜单的两张实现方式
- 对ArrayList<T>中按照T的某个属性进行排序
- Windows下React Native安装
- Java程序语言设计基础篇原书第十版第三章答案编程练习题