[Ynoi2012]D1T3
https://www.luogu.org/problemnew/show/P5311
题解
先把点分树建出来。
对于吗,每一个询问\((l,r,x)\),我们对于x要找到它在点分树上最靠上的父亲节点使得两点之间的点在\(l \sim r\)中。
然后问题就变成了从一个根出发,可以经过\(l \sim r\)的点,能访问的颜色个数。
那么因为有了点分树,所以我们对于每个点\(dfs\)它的子树的复杂度是对的。
然后对于每个根,我们求出它的子树里的所有点的到根的路径上的编号最大最小值,然后考虑这个点产生贡献的条件,发现就是个二维偏序。
但是还有相同颜色算两边的情况,这个在扫描线的时候用单调性去重就好了,具体来说对于\(r\)都在合法范围内的点,\(l\)更大越优,所以我们只需要保留最大的\(l\)就好了。
代码
#include<bits/stdc++.h>
#define N 100009
#define mm make_pair
using namespace std;
typedef long long ll;
vector<int>fa[N];
vector<pair<int,int> >v[N];
bool vis[N];
int tot,head[N],dp[N],ans[N],size[N],root,tong[N],a[N],n,m,sum;
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct edge{
int n,to;
}e[N<<1];
struct BIT{
int tr[N];
inline void add(int x,int y){while(x)tr[x]+=y,x-=x&-x;}
inline int query(int x){int ans=0;while(x<=n)ans+=tr[x],x+=x&-x;return ans;}
}T;
struct node{
int id,l,r,opt;
inline bool operator <(const node &b)const{
if(r!=b.r)return r<b.r;
return opt<b.opt;
}
};
vector<node>b[N];
vector<node>::iterator it;
inline void add(int u,int v){
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
}
void getroot(int u,int fa){
dp[u]=0;size[u]=1;
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;
getroot(v,u);
size[u]+=size[v];
dp[u]=max(dp[u],size[v]);
}
dp[u]=max(dp[u],sum-size[u]);
if(dp[u]<dp[root])root=u;
}
void getsize(int u,int fa){
size[u]=1;
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;
getsize(v,u);
size[u]+=size[v];
}
}
void work(int u,int ff,int ma,int mi,int top){
ma=max(ma,u);mi=min(mi,u);
fa[u].push_back(top);
v[u].push_back(mm(mi,ma));
for(int i=head[u];i;i=e[i].n)if(e[i].to!=ff&&!vis[e[i].to]){
int v=e[i].to;
work(v,u,ma,mi,top);
}
}
void getcalc(int u,int fa,int mi,int ma){
mi=min(mi,u);ma=max(ma,u);
b[root].push_back(node{a[u],mi,ma,0});
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;
getcalc(v,u,mi,ma);
}
}
void solve(int u){
vis[u]=1;
getcalc(u,0,u,u);
v[u].push_back(mm(u,u));fa[u].push_back(u);
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
root=n+1;sum=size[v];
getroot(v,u);getsize(root,0);
work(v,0,u,u,u);
solve(root);
}
}
int main(){
n=rd();m=rd();
for(int i=1;i<=n;++i)a[i]=rd();
int x,y;
for(int i=1;i<n;++i){
x=rd();y=rd();
add(x,y);add(y,x);
}
root=n+1;sum=n;dp[root]=n+1;
getroot(1,0);getsize(root,0);
solve(root);
int l,r;
for(int i=1;i<=m;++i){
l=rd();r=rd();x=rd();
for(int j=0;j<fa[x].size();++j){
int y=fa[x][j],ls=v[x][j].first,rs=v[x][j].second;
if(ls>=l&&rs<=r){x=y;break;}
}
b[x].push_back(node{i,l,r,1});
}
for(int i=1;i<=n;++i){
sort(b[i].begin(),b[i].end());
for(it=b[i].begin();it!=b[i].end();++it){
if(!it->opt){
if(tong[it->id]<it->l){
if(tong[it->id])T.add(tong[it->id],-1);
T.add(it->l,1);
tong[it->id]=it->l;
}
}
else{
ans[it->id]=T.query(it->l);
}
}
for(it=b[i].begin();it!=b[i].end();++it)
if(!it->opt){
if(tong[it->id])T.add(tong[it->id],-1),tong[it->id]=0;
}
b[i].clear();
}
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}
[Ynoi2012]D1T3的更多相关文章
- ZROI 暑期高端峰会 A班 Day4 树上数据结构
FBI Warning:本文含有大量人类的本质之一. 你经历过绝望吗? [ZJOI2007]捉迷藏 询问树上最远黑点对. 动态边分治可以比点分治少一个 \(\log\). bzoj3730 咕了. [ ...
- zhengrui集训D1-D5笔记
Day_1 计数 它咕掉了 Day_1 序列数据结构 它咕掉了 Day_2 线性代数 高斯消元\Large{高斯消元}高斯消元 普通版:略 模质数:求逆 模合数:exgcd 逆矩阵\Large{逆矩阵 ...
- [luogu P3953] [noip2017 d1t3] 逛公园
[luogu P3953] [noip2017 d1t3] 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张$N$个点$M$条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,$N ...
- 【NOIP2017 D1T3】逛公园
NOIP2017 D1T3 逛公园 题意:给一个有向图,每条边有权值,问从\(1\)到\(N\)的长度不超过最短路长度\(+K\)的路径条数.如果有无数条则输出\(-1\). 思路:我们首先扔掉\(- ...
- [2018HN省队集训D1T3] Or
[2018HN省队集训D1T3] Or 题意 给定 \(n\) 和 \(k\), 求长度为 \(n\) 的满足下列条件的数列的数量模 \(998244353\) 的值: 所有值在 \([1,2^k)\ ...
- noip 2018 D1T3 赛道修建
noip 2018 D1T3 赛道修建 首先考虑二分答案,这时需要的就是对于一个长度求出能在树中选出来的最多的路径条数.考虑到一条路径是由一条向上的路径与一条向下的路径构成,或者仅仅是向上或向下的路径 ...
- [NOIP2018 TG D1T3]赛道修建
题目大意:$NOIP2018\;TG\;D1T3$ 题解:题目要求最短的赛道的长度最大,可以想达到二分答案,接着就是一个显然的树形$DP$. 发现对于一个点,它子树中若有两条链接起来比要求的答案大,一 ...
- 开车旅行 【NOIP2012 D1T3】
开车旅行 [NOIP2012 D1T3] 倍增 首先令\(a[i]\)表示从i出发最近的城市下标,\(b[i]\)表示从i出发第二近的城市下标 可以维护一个\(\text{set<pair< ...
- 嵊州D1T3 睡美人航班
嵊州D1T3 睡美人航班 不知不觉中,我对她的爱意已经达到了 n. 是这样子的,第 1 分钟,我对她的爱意值是 (1, 1). 假如当第 x 分钟时我对她的爱意值是 (a, b),那么第 x + 1 ...
随机推荐
- Map m=new HashMap()
Map<String,String> m=new HashMap<String,String>() 等于 HashMap<String,String> hashMa ...
- CSP2019 —— 今年欢笑复明年,不知退役在眼前
关于2019CSP-J/-S的一些体会 又是一年退役季,想起在群里看到大佬的一句诗,感慨万千. 今年欢笑复明年,不知退役在眼前 于是便心生文意,随便写点东西来给自己康康. 先说说这次的成绩吧.大家应该 ...
- 防止XSRF 解决方案
1.首先在表单提交页面生成校验使用的Token public ActionResult Index() { //Token验证需要使用的token string token = System.Guid ...
- mysql 函数 时间函数,数学函数,字符串函数,条件判断函数
=========================================== mysql 相关函数 ============================================= ...
- Hibernate的HQL多表查询
HQL的内连接查询 对于HQL内链接查询,查询的是两张表的数据,这两张表的数据首先是保存在数组之中,然后在将每一个数组保存在List集合之中进行返回 代码片段: @Test // 内连接 public ...
- Git-第四篇廖雪峰Git教程学习笔记(3)远程仓库,克隆远端库
1.本次连接的是gitHub仓库. 1>创建SSH Key. ssh-keygen -t rsa -C "youremail@example.com" lfy@lfy-PC ...
- 解决MySQL报错:Access denied for user ‘root’@‘localhost’(using password: YES)
Windows 10(mysql5.1) 修改配置文件 找到MySQL安装目录下配置文件my.ini(在我的win10环境下,其路径为C:\ProgramData\MySQL\MySQL Server ...
- 洛谷 P2024 [NOI2001]食物链(种类并查集,加权并查集)
传送门 解题思路 加权并查集: 什么是加权并查集? 就是记录着每个节点到它的父亲的信息(权值等). 难点:在路径压缩和合并节点时把本节点到父亲的权值转化为到根节点的权值 怎么转化呢? 每道题都不一样Q ...
- [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并)
[BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并) 题面 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1 ...
- BZOJ 3252题解(贪心+dfs序+线段树)
题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...