题意:给一棵树,点有颜色,qqq 次询问,每次给定 l,r,xl,r,xl,r,x ,求只保留编号在 [l,r][l,r][l,r] 中的点时点 xxx 所在连通块的颜色数。

所有数 ≤105\leq 10^5≤105

题目背景好评

首先所有颜色不同的话就是数连通块大小,先想想这个怎么做。

然后不会做,拜拜了您嘞


考察所求的 xxx 所在连通块在点分治中的过程,这个连通块一直是完整的直到一个分治中心踩到了这个连通块中的一个点。建出点分树后,我们预处理每个点 与所有点分树上的祖先在原树上的路径经过的点编号的最小值与最大值,然后每个询问把 xxx 暴力跳祖先就可以找到这个点。

这个点点分树上的子树的点包含了所求的连通块,且这个点在连通块内。对于子树内的点,它在连通块内当且仅当到子树的根的路径的编号范围被询问区间完全包含。所以对每个点 dfs 一遍子树,然后就是喜闻乐见的主对角线矩形数颜色问题。

把询问离线(这道题里面本来就是离线的)挂在右端点上,然后移动右端点,维护每种颜色的点的左端点的最大值,树状数组上加一下就可以了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <vector>
#include <algorithm>
#define MAXN 100005
using namespace std;
const int INF=0x7fffffff;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
int col[MAXN];
struct node{int l,r,val;};
//ancestor: val=the index of the ancestor
//son: val=the color of the son
//query: val=the index of the query
vector<int> e[MAXN];
vector<node> p[MAXN],s[MAXN],q[MAXN];
int rt,siz[MAXN],maxp[MAXN],vis[MAXN];
void findrt(int u,int f,int sum)
{siz[u]=1,maxp[u]=0;for (int i=0;i<(int)e[u].size();i++)if (!vis[e[u][i]]&&e[u][i]!=f){findrt(e[u][i],u,sum);siz[u]+=siz[e[u][i]];maxp[u]=max(maxp[u],siz[e[u][i]]);}maxp[u]=max(maxp[u],sum-siz[u]);if (maxp[u]<maxp[rt]) rt=u;
}
void dfs(int u,int f,int l,int r)
{p[u].push_back((node){l,r,rt});s[rt].push_back((node){l,r,col[u]});siz[u]=1;for (int i=0;i<(int)e[u].size();i++)if (!vis[e[u][i]]&&e[u][i]!=f){dfs(e[u][i],u,min(l,e[u][i]),max(r,e[u][i]));siz[u]+=siz[e[u][i]];}
}
void build()
{vis[rt]=1;dfs(rt,0,rt,rt);int u=rt;for (int i=0;i<(int)e[u].size();i++)if (!vis[e[u][i]]){rt=0,findrt(e[u][i],0,siz[e[u][i]]);build();}
}
const int N=1e5;
struct BIT
{int s[MAXN];inline int lowbit(const int& x){return x&-x;}inline void modify(int x,int v){for (;x<=N;s[x]+=v,x+=lowbit(x));}inline int query(int x,int ans=0){for (;x;ans+=s[x],x-=lowbit(x));return ans;}
}bit;
int mx[MAXN];
vector<node> tf[MAXN],tq[MAXN];
vector<int> lis;
int ans[MAXN];
int main()
{maxp[0]=INF;int n,m;n=read(),m=read();for (int i=1;i<=n;i++) col[i]=read();for (int i=1;i<n;i++) {int u,v;u=read(),v=read();e[u].push_back(v),e[v].push_back(u);}findrt(1,0,n),build();for (int T=1;T<=m;T++){int l,r,x;l=read(),r=read(),x=read();for (int i=0;i<(int)p[x].size();i++)if (l<=p[x][i].l&&p[x][i].r<=r){q[p[x][i].val].push_back((node){l,r,T});break;}}for (int u=1;u<=n;u++){lis.clear();for (int i=0;i<(int)s[u].size();i++)tf[s[u][i].r].push_back(s[u][i]),lis.push_back(s[u][i].r);for (int i=0;i<(int)q[u].size();i++)tq[q[u][i].r].push_back(q[u][i]),lis.push_back(q[u][i].r);sort(lis.begin(),lis.end());lis.erase(unique(lis.begin(),lis.end()),lis.end());for (int t=0;t<(int)lis.size();t++){int r=lis[t];for (int i=0;i<(int)tf[r].size();i++)if (tf[r][i].l>mx[tf[r][i].val]){if (mx[tf[r][i].val]) bit.modify(mx[tf[r][i].val],-1);bit.modify(mx[tf[r][i].val]=tf[r][i].l,1);}for (int i=0;i<(int)tq[r].size();i++)ans[tq[r][i].val]=bit.query(r)-bit.query(tq[r][i].l-1);}for (int i=0;i<(int)s[u].size();i++){if (mx[s[u][i].val]) bit.modify(mx[s[u][i].val],-1);mx[s[u][i].val]=0;}for (int i=0;i<(int)lis.size();i++) tf[lis[i]].clear(),tq[lis[i]].clear();}for (int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}

【Ynoi2011】成都七中【树论】【点分树】【离线】【树状数组】相关推荐

  1. [NOI Online 2022 提高组] 丹钓战(单调栈 + 树状数组 / 主席树)

    problem luogu-P8251 solution 按照题意模拟单调栈. 求出对于 iii 而言,当时单调栈的栈顶元素记为 pip_ipi​. 如果到 iii 时,栈顶已经为 pip_ipi​ ...

  2. UVA 12086 (树状数组)

    题目网址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. P5311-[Ynoi2011]成都七中【点分树,树状数组】

    正题 题目链接:https://www.luogu.com.cn/problem/P5311 题目大意 给出nnn个点的一棵树,每个节点有一个颜色,mmm次询问提出区间[l,r][l,r][l,r]的 ...

  4. [蓝桥杯][算法提高VIP]分苹果(差分||树状数组)

    题目描述 小朋友排成一排,老师给他们分苹果. 小朋友从左到右标号1-N.有M个老师,每次第i个老师会给第Li个到第Ri个,一共Ri-Li+1个小朋友每人发Ci个苹果. 最后老师想知道每个小朋友有多少苹 ...

  5. CCF201709-5 除法(100分)【树状数组+线段树】

    试题编号: 201709-5 试题名称: 除法 时间限制: 10.0s 内存限制: 256.0MB 问题描述: 问题描述 小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次 ...

  6. bzoj2683:简单题(树状数组套CDQ分分治)

    CDQ(陈丹琦)分治 CDQ显然是一个人的名字(2008NOI金牌选手陈丹琦) 这种离线的分治算法在算法界被称为"CDQ分治".  首先回忆一下归并排序的分治, 它的操作是将数组二 ...

  7. 智慧树考试复制粘贴会检测吗_智慧树考试可以分屏吗?切屏会被发现吗

    智慧树可以在线考试,有不少朋友想知道智慧树考试切屏有记录吗?智慧树考试分屏会被发现吗?下面小编就为大家带来相关介绍,感兴趣的朋友们快来一起了解下吧! -->>智慧树下载< 智慧树考试 ...

  8. 1057 Stack (30 分)【难度: 中 / 知识点: 树状数组 STL】

    https://pintia.cn/problem-sets/994805342720868352/problems/994805417945710592 本题的一个最大的难点,就是如何给一个动态的区 ...

  9. 笛卡尔树 (25 分)笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字

    立志用最少的代码做最高效的表达 笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2.首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大.其次所有结点的 ...

最新文章

  1. Jenkins简介及在Windows上的简单使用示例
  2. 智能媒体管理产品文档转换/预览功能介绍(4)--快速搭建
  3. 《C++标准程序库》读书笔记(三)
  4. 财务 计算机网络,计算机网络技术在财务系统中的应用
  5. linux fastQC 操作命令,linux-ubuntu下fastQC的安裝及使用
  6. log4j的配置方法
  7. ajax结构图,Vuex结构图及用法
  8. c#实现对sqlserver的增删改操做 1117
  9. phalcon的一些中文手册和帮助文档地址收集
  10. 向域管理转型所遇到的问题
  11. 吴军《谷歌面试题:倒置英文句子》
  12. 知道ip地址如何进入电脑_如何防止局域网电脑IP地址冲突
  13. unity3d面试题
  14. 调色板程序c语言,用C语言开发NES游戏(CC65)05、调色板
  15. 人工智能实战第六次作业_张绍恺
  16. [XMAN2018排位赛]通行证
  17. 数26个大写字母里带圈的字母个数
  18. 购物页面点叉号二维码隐藏的做法
  19. C++学生管理系统课程设计
  20. 再谈宋星博客的留言与seo培训联盟

热门文章

  1. php ftp 创建文件夹失败,PHP使用FTP函数创建目录
  2. 万物皆可傅里叶!用傅里叶变换还能画出世界名画!
  3. 美女晕倒怎么办?二哈:这不是一滋就醒......
  4. 这家AI公司用面具破解中国人脸识别系统!微信、支付宝、火车站无一幸免
  5. 这些Python骚操作,你值得拥有
  6. 像小猪佩奇那样生活,需要多少钱?
  7. 一位像素艺术家用39张动图,将大自然的唯美尽收眼底…
  8. 重磅大礼!100本《机器学习》by周志华,免费送!
  9. python web前端开发面试_面试前端,听听别人怎么说!
  10. php显示前60个字,DEDECMS中怎么让文章标题栏突破60个字符