考完D2发现自己简直zz了。。。花式扔基本分

首先这道题有个显然的套路:树上一些点到一个定点的距离和=这些点深度和+点数*定点深度和-2*lca深度和

——上一次见这个套路是LNOI2014,上次做的时候还比较naive:http://www.cnblogs.com/wanglichao/p/6425893.html

这次考场上也只想到这一步了,,并没有发现广义线段树的奇特性质

奇特性质:被选中的从左到右一定是一串右儿子和一串左儿子,而且都是挂在l-1到r+1上的连续右(左)儿子

这么一来,一个询问可以分成两部分,这两部分都可以O(n)预处理出来

在预处理的时候考虑维护两个东西:从根节点到当前点的链上所直接挂的所有右儿子的个数(记为sum[i])和深度和(sumd[i])

那么在统计的时候 这些点深度和+点数*定点深度和-2*lca深度和 可以轻松算出

(一脸懵逼.jpg)

Q:如何算lca深度和?

A:分类讨论,计算询问的定点挂到链上是哪里(以下称为悬挂点x)

①悬挂点以上的点与定点的lca深度为自己深度-1,所以总和为“sumd[x]-sum[x]”

②悬挂点的右儿子如果被算在答案里,那么深度就是"dep[x]+1"

③悬挂点以下的点与定点的lca深度一定为dep[x],总和为"(sum[l-1]-sum[x])*dep[x]"

求和即可(注意细节)

左儿子同理

Q:l=1或者r=n怎么办

A:只算半边(自行理解,不可言传)

上个代码冷静一下(目前uoj上最短榜第一来自这个代码微改@wzf2000):

 #include <bits/stdc++.h>
#define bel(x,y) (L[x]>=L[y] && R[x]<=R[y])
using namespace std;
long long n,N,IN,m,u,l,r,LOG;
long long mer[],ls[],rs[],sum[][],dep[],sd[][];
long long fa[][];
long long L[],R[],nod[];
long long lca(long long a,long long b)
{
if(bel(a,b)) return b;
if(bel(b,a)) return a;
long long now=a;
for(long long i=LOG;i>=;i--)
if(fa[now][i] && !bel(b,fa[now][i])) now=fa[now][i];
return fa[now][];
}
void Dfs(long long now)
{
if(!ls[now]) return;
sum[rs[now]][]=sum[now][];
sum[rs[now]][]=sum[now][]+;
sum[ls[now]][]=sum[now][]+;
sum[ls[now]][]=sum[now][];
dep[ls[now]]=dep[now]+;
dep[rs[now]]=dep[now]+;
sd[rs[now]][]=sd[now][];
sd[rs[now]][]=sd[now][]+dep[now]+;
sd[ls[now]][]=sd[now][]+dep[now]+;
sd[ls[now]][]=sd[now][];
Dfs(ls[now]);
Dfs(rs[now]);
}
long long dfs(long long l,long long r)
{
long long now=++N;
L[now]=l;R[now]=r;
for(long long i=;fa[fa[now][i]][i];i++) fa[now][i+]=fa[fa[now][i]][i];
if(l==r) return nod[l]=now;
long long me=mer[IN++];
fa[N+][]=now;
ls[now]=dfs(l,me);
fa[N+][]=now;
rs[now]=dfs(me+,r);
return now;
}
long long getl(long long l)
{
long long lc=lca(l,u);
long long now=dep[lc]*(sum[l][]-sum[lc][])+(bel(l,ls[lc]) && lc!=u)+sd[lc][]-sum[lc][];
long long ans=sd[l][]+sum[l][]*dep[u]-now*;
return ans;
}
long long getr(long long r)
{
long long lc=lca(r,u);
long long now=dep[lc]*(sum[r][]-sum[lc][])+(bel(r,rs[lc]) && lc!=u)+sd[lc][]-sum[lc][];
long long ans=sd[r][]+sum[r][]*dep[u]-now*;
return ans;
}
int main()
{
scanf("%d",&n);
for(long long i=;i<=n;i<<=)
LOG++;
for(long long i=;i<n;i++)
scanf("%d",&mer[i]);
IN=;
dfs(,n);
Dfs();
scanf("%d",&m);
for(long long i=;i<=m;i++)
{
scanf("%d%d%d",&u,&l,&r);
--l;++r;
if(!l && r>n)
{
printf("%d\n",dep[u]);
continue;
}
long long ans=;
if(l)
ans+=getl(nod[l])-((r<=n)?getl(ls[lca(nod[l],nod[r])]):);
if(r<=n)
ans+=getr(nod[r])-(l?getr(rs[lca(nod[l],nod[r])]):);
printf("%lld\n",ans);
}
return ;
}

ZJOI2017 day2 T2 线段树 想法题的更多相关文章

  1. SPOJ - DWARFLOG Manipulate Dwarfs 线段树+想法题;

    题意:给你2e5个矮人,编号1~N.有2e5个操作:操作1 读取x,y,交换编号为x,y的矮人.操作2 读取AB 判断编号为A,A+1····B的矮人是否连续(不必有序). 题解:首先用pos[i]保 ...

  2. 【LOJ6062】「2017 山东一轮集训 Day2」Pair(线段树套路题)

    点此看题面 大致题意: 给出一个长度为\(n\)的数列\(a\)和一个长度为\(m\)的数列\(b\),求\(a\)有多少个长度为\(m\)的子串与\(b\)匹配.数列匹配指存在一种方案使两个数列中的 ...

  3. hdu-1540线段树刷题

    title: hdu-1540线段树刷题 date: 2018-10-18 19:55:21 tags: acm 刷题 categories: ACM-线段树 概述 哇,,,这道线段树的题可以说是到目 ...

  4. [AHOI 2009] 维护序列(线段树模板题)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...

  5. POJ 3468 线段树裸题

    这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了A ...

  6. hdu-5023线段树刷题

    title: hdu-5023线段树刷题 date: 2018-10-18 13:32:13 tags: acm 刷题 categories: ACM-线段树 概述 这道题和上次做的那道染色问题一样, ...

  7. poj-2777线段树刷题

    title: poj-2777线段树刷题 date: 2018-10-16 20:01:07 tags: acm 刷题 categories: ACM-线段树 概述 这道题是一道线段树的染色问题,,, ...

  8. zoj-1610线段树刷题

    title: zoj-1610线段树刷题 date: 2018-10-16 16:49:47 tags: acm 刷题 categories: ACM-线段树 概述 这道题是一道简单的线段树区间染色问 ...

  9. Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017 - Final Round Div. 2 Edition) E - Nikita and stack 线段树好题

    http://codeforces.com/contest/760/problem/E 题目大意:现在对栈有m个操作,但是顺序是乱的,现在每输入一个操作要求你输出当前的栈顶, 注意,已有操作要按它们的 ...

随机推荐

  1. [RK3288][Android6.0] 调试笔记 --- eMMC分区号和名字的对应【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/77318410 Platform: Rockchip OS: Android 6.0 Kern ...

  2. 多线程设计模式(一) Single Threaded Execution

    这里有一座独木桥.因为桥身非常的细,一次只能允许一个人通过.当这个人没有下桥,另一个人就不能过桥.如果桥上同时又两个人,桥就会因为无法承重而破碎而掉落河里. 这就是Single Threaded Ex ...

  3. 51Nod - 1821:最优集合 (求第一个不能被表示为多个数的和的数)(不错的动脑题)

    一个集合S的优美值定义为:最大的x,满足对于任意i∈1,x1,x,都存在一个S的子集S',使得S'中元素之和为i. 给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2,以及一个数k,要求选择 ...

  4. oracle下 启动subversion命令 及 oracle相关服务启动备忘

    linux shell下  svnserve - d -r + 目录   例如:svnserve -d -r /svn 启动 svn服务. 访问svn://192.168.0.120/kjcg 测试. ...

  5. 「USACO16OPEN」「LuoguP3146」248(区间dp

    题目描述 Bessie likes downloading games to play on her cell phone, even though she doesfind the small to ...

  6. 洛谷 1312 Mayan游戏——暴搜+剪枝

    题目:https://www.luogu.org/problemnew/show/P1312 自己写了很久.又T又WA的. 发现对题理解有误.改完后应该只有T了,但还是T的. 自己写了许多剪枝,很鸡肋 ...

  7. node process-进程

    process对象是一个全局变量,提供Node.js进程的有关信息以及控制进程.因为是全局变量所以可以直接使用

  8. win10文件夹或文件已在另一程序中打开

    我们在对文件或文件夹进行删除.移动.重命名等操作时,系统可能提示“操作无法完成,因为其中的文件夹已在另一程序中打开,请关闭该文件或文件夹,然后重试.”,遇到这种情况我们应该怎么办呢?请看下文. 方法/ ...

  9. iOS 中这些是否熟练掌握——(2)

    接上一篇博文,本篇博文是作者原创,用于记录从网上查阅的一些资料,并对自己的知识体系进行一下总结,成文以供学习使用. 1.Cocoa Touch 包含了什么?不包含什么?与 Cocoa 有什么区别? 相 ...

  10. 可移植的配置visual studio工程第三方库

    现在编程有太多的好用的第三方库,例如 计算机视觉方面的opencv c++的扩充库boost 特殊的第三方库,相机库,通讯库等 使用这些库给我们带来了极大的便利,同时也有很多困扰.这个工程在我电脑上明 ...