裸题,树状数组区间修改+单点查询。当然要稍微讨论一下链的左右端点是否修改的情况咯。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 300001
int en,v[N<<1],first[N],next[N<<1],n;
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
int dep[N],siz[N],fa[N],son[N],top[N],Num[N],tot;
void dfs(int U,int d)
{
dep[U]=d;
siz[U]=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
{
fa[v[i]]=U;
dfs(v[i],d+1);
siz[U]+=siz[v[i]];
if(siz[v[i]]>siz[son[U]])
son[U]=v[i];
}
}
void dfs2(int U)
{
if(son[U])
{
top[son[U]]=top[U];
Num[son[U]]=++tot;
dfs2(son[U]);
}
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U]&&v[i]!=son[U])
{
top[v[i]]=v[i];
Num[v[i]]=++tot;
dfs2(v[i]);
}
}
int SIZ[N],TOP[N],sz;
void dfs3(int U)
{
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
{
if(SIZ[TOP[U]]<sz)
{
TOP[v[i]]=TOP[U];
++SIZ[TOP[U]];
}
dfs3(v[i]);
}
}
int lca(int U,int V)
{
while(U!=V)
{
if(TOP[U]!=TOP[V])
{
if(dep[TOP[U]]<dep[TOP[V]])
swap(U,V);
U=fa[TOP[U]];
}
else
{
if(dep[U]<dep[V])
swap(U,V);
U=fa[U];
}
}
return U;
}
int d[N];
void add_node(int p,const int &v){for(;p<=n;p+=(p&(-p))) d[p]+=v;}
void add_range(const int &L,const int &R){add_node(L,1);if(R!=n)add_node(R+1,-1);}
int query(int p){int res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;}
void update(int U,int V)
{
int f1=top[U],f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(U,V);
}
add_range(Num[f1],Num[U]);
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
add_range(Num[U],Num[V]);
}
int cnt,LL[N],RR[N];
void dfs4(int U)
{
LL[U]=++cnt;
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
dfs4(v[i]);
RR[U]=cnt;
}
int xu[N];
void work(const int &L,const int &R,const int &op)
{
if(op==n-1)
{
if(fa[L]==R||fa[R]==L) return;
int LCA=lca(L,R);
if(LCA==L)
{
for(int i=first[L];i;i=next[i])
if(v[i]!=fa[L]&&LL[R]>=LL[v[i]]&&LL[R]<=RR[v[i]])
{
update(v[i],fa[R]);
return;
}
}
else if(LCA==R)
{
for(int i=first[R];i;i=next[i])
if(v[i]!=fa[R]&&LL[L]>=LL[v[i]]&&LL[L]<=RR[v[i]])
{
update(fa[L],v[i]);
return;
}
}
else update(fa[L],fa[R]);
return;
}
if(lca(L,R)==L)
{
for(int i=first[L];i;i=next[i])
if(v[i]!=fa[L]&&LL[R]>=LL[v[i]]&&LL[R]<=RR[v[i]])
{
update(v[i],R);
return;
}
}
else update(fa[L],R);
}
int main()
{
int A,B;
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&xu[i]);
for(int i=1;i<n;++i)
{
scanf("%d%d",&A,&B);
AddEdge(A,B);
AddEdge(B,A);
}
top[1]=1;
Num[1]=++tot;
dfs(1,1);
dfs2(1);
sz=sqrt(n); if(!sz) sz=1;
for(int i=1;i<=n;i++)
{
SIZ[i]=1;
TOP[i]=i;
}
dfs3(1);
dfs4(1);
if(n==2)
{
work(xu[2],xu[1],0);
goto OUT;
}
update(xu[1],xu[2]);
for(int i=2;i<n;++i)
work(xu[i],xu[i+1],i);
OUT:for(int i=1;i<=n;++i)
printf("%d\n",query(Num[i]));
return 0;
}

【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家的更多相关文章

  1. [BZOJ3631][JLOI2014]松鼠的新家(树链剖分)

    [BZOJ3631] 树剖模板题了, Code #include <cstdio> #include <algorithm> #define MID int mid=(l+r) ...

  2. 树链剖分的一种妙用与一类树链修改单点查询问题的时间复杂度优化——2018ACM陕西邀请赛J题

    题目描述 有一棵树,每个结点有一个灯(初始均是关着的).每个灯能对该位置和相邻结点贡献1的亮度.现有两种操作: (1)将一条链上的灯状态翻转,开变关.关变开: (2)查询一个结点的亮度. 数据规模:\ ...

  3. BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )

    裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...

  4. 树链剖分 [JLOI2014]松鼠的新家

    [JLOI2014]松鼠的新家 时间限制: 1 Sec  内存限制: 128 MB 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达, ...

  5. [JLOI2014]松鼠的新家(树链剖分)

    [JLOI2014]松鼠的新家(luogu) Description 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间 ...

  6. 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...

  7. Bzoj 3631: [JLOI2014]松鼠的新家(树链剖分+线段树)

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MB Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个 ...

  8. [JLOI2014]松鼠的新家 (树剖)

    题目 P3258 [JLOI2014]松鼠的新家 解析 非常裸的一道树剖题 链上修改+单点查询的板子 记录一下所经过的点\(now[i]\),每次更新\(now[i-1]到now[i]\) 我们链上更 ...

  9. 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)

    题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...

随机推荐

  1. oracle数据库导入导出方法

    Oracle Database 10g以后引入了最新的数据泵(Data Dump)技术,使DBA或开发人员可以将数据库元数据(对象定义)和数据快速移动到另一个oracle数据库中. 数据泵导出导入(E ...

  2. 利用WebStorm来管理你的Github

    什么是Github Github是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目,以最简单的方式来说,其实就是一个代码库,上面有全世界无数优秀的码农上传自己的作品和大家共享(当然 ...

  3. 简单配置oracle11g

    一.配置 Systemd file(开机可以自动oracle,也可以查看启动状态) a.定义环境变量 [oracle@ol7 ~]$ cat /etc/sysconfig/DB11G.oracledb ...

  4. Ubuntu1604 install netease-cloud music

    Two issue: 1. There is no voice on my computer, and the system was mute and cannot unmute. eric@E641 ...

  5. bzoj1503: [NOI2004]郁闷的出纳员 fhqtreap版

    这道题写法和之前差不多 但是fhqtreap在加点的时候为了同时维护大根堆以及二叉排序树的性质所以插入时也要注意分裂 fhqteap需要判断指针是否为空 不然就会re 这个我调了很久 #include ...

  6. 【CF1027E】Inverse Coloring(DP)

    题意:给出一个n*n的矩阵,要求在每个位置涂上黑/白色, 要求满足:任意相邻的两行,其颜色要么完全相同,要么完全相反 任意相邻的两列,其颜色也要么相同要么完全相反 且这个矩形中,不存在任意一个大小大于 ...

  7. BestCoder Round #39 解题报告

    现场只做出前三题w 不过不管怎样这既是第一次认真打BC 又是第一次体验用在线编译器调代码 订正最后一题花了今天一整个下午(呜呜 收获还是比较大的^_^ Delete wld有n个数(a1,a2,... ...

  8. set .net principle

    var ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(FormsA ...

  9. JS高级技巧(简洁版)

    高级函数 由于在JS中,所有的函数都是对象,所以使用函数指针十分简单,也是这些东西使JS函数有趣且强大 安全的类型检测 JS内置的类型检测机制并不是完全可靠的 typeof 操作符返回一个字符串,表示 ...

  10. [bzoj4766]文艺计算姬——完全二分图生成树个数

    Brief Description 求\(K_{n,m}\) Algorithm Design 首先我们有(Matrix Tree)定理,可以暴力生成几组答案,发现一些规律: \[K_{n,m} = ...