[bzoj省选十连测推广赛2]T2七彩树
抄自:http://blog.csdn.net/coldef/article/details/61412577
当时看了就不会,看了别人的题解不懂怎么维护,最后抄了个代码.......
给定一棵n个点的树,每个点有颜色。m次询问,每次询问一个节点子树中深度和这个点深度之差<=d的点的颜色数量。多组数据,每组n,m<=10^5,总共小于500000
题解:如果不考虑深度,我们可以把相同颜色的节点按照dfs序排序,然后相邻节点在lca处-1,这样求子树和就可以求出答案了。考虑深度,我们就用主席树以深度为时间戳来维护呗。感觉看了原作者的代码学到了很多,原作者用set来维护相邻的相同颜色的节点真的妙。
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<set>
#include<algorithm>
#define mp(x,y) make_pair
#define pa pair<int,int>
#define itr set<pair<int,int> >::iterator
#define MAXN 100000
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} int n,m,cnt,cc,dfn,head[MAXN+],p[MAXN+];
int fa[MAXN+][],rt[MAXN+],dep[MAXN+],nl[MAXN+],nr[MAXN+],col[MAXN+];
struct TREE{
int l,r,x,lt,rt;
}T[];
vector<int> v[MAXN+];
set<pa > ev[MAXN+];
struct edge{
int to,next;
}e[*MAXN+];
inline void ins(int f,int t){e[++cc].next=head[f];head[f]=cc;e[cc].to=t;}
bool cmp(int x,int y){return nl[x]<nl[y];}
bool cmp2(int x,int y){return dep[x]<dep[y];} void dfs(int x,int d)
{
dep[x]=d;nl[x]=++dfn;
for(int i=head[x];i;i=e[i].next)dfs(e[i].to,d+);
nr[x]=dfn;
} int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);int th=dep[x]-dep[y];
for(int i=;th;th>>=,++i)if(th&)x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][];
} void renew(int x0,int&x,int k,int ad,int l,int r)
{
// cout<<"renew"<<x0<<" "<<x<<" "<<k<<" "<<ad<<" "<<l<<" "<<r<<endl;
x=++cnt;T[x].lt=T[x0].lt;T[x].rt=T[x0].rt;
T[x].l=l;T[x].r=r;T[x].x=T[x0].x+ad;
if(l==r)return;int mid=(l+r)>>;
if(k<=mid)renew(T[x0].lt,T[x].lt,k,ad,l,mid);
else renew(T[x0].rt,T[x].rt,k,ad,mid+,r);
} int query(int k,int l,int r)
{
//cout<<"query"<<k<<" "<<l<<" "<<r<<endl;
if(!k)return ;
if(T[k].l==l&&T[k].r==r)return T[k].x;
int mid=(T[k].l+T[k].r)>>;
if(r<=mid)return query(T[k].lt,l,r);
else if(l>mid) return query(T[k].rt,l,r);
else return query(T[k].lt,l,mid)+query(T[k].rt,mid+,r);
} int main()
{
int T=read();
for(int i=;i<=T;i++)
{
cnt=cc=dfn=;for(int i=;i<=n;i++)v[i].clear();
memset(head,,sizeof(head));memset(rt,,sizeof(rt));n=read();m=read();
for(int i=;i<=n;i++){col[i]=read();}
for(int i=;i<=n;i++){fa[i][]=read();ins(fa[i][],i);}
dfs(,);
for(int i=;i<;i++)for(int j=;j<=n;j++)
fa[j][i]=fa[fa[j][i-]][i-];
for(int i=;i<=n;i++)p[i]=i;sort(p+,p+n+,cmp2);
for(int i=;i<=n;i++)
{
int x=p[i],y=p[i-];
renew(rt[dep[y]],rt[dep[x]],nl[x],,,n);
if(ev[col[x]].empty()){ev[col[x]].insert(pa(nl[x],x));continue;}
ev[col[x]].insert(pa(nl[x],x));
itr it=ev[col[x]].find(pa(nl[x],x));
itr a=--it;it=ev[col[x]].find(pa(nl[x],x));itr b=++it;
if(a!=ev[col[x]].end()&&b!=ev[col[x]].end())renew(rt[dep[x]],rt[dep[x]],nl[lca(a->second,b->second)],,,n);
if(a!=ev[col[x]].end())renew(rt[dep[x]],rt[dep[x]],nl[lca(x,a->second)],-,,n);
if(b!=ev[col[x]].end())renew(rt[dep[x]],rt[dep[x]],nl[lca(x,b->second)],-,,n);
}
int last=;
for(int i=;i<=n;i++)ev[i].clear();
for(int i=;i<=m;i++)
{
int u=read()^last,v=read()^last;
last=query(rt[min(dep[p[n]],dep[u]+v)],nl[u],nr[u]);
printf("%d\n",last);
}
}
return ;
}
我好菜啊都不会。
[bzoj省选十连测推广赛2]T2七彩树的更多相关文章
- [BZOJ]2017省队十连测推广赛1 T2.七彩树
题目大意:给你一棵n个点的树,每个点有颜色,m次询问,每次询问一个点x的子树内深度不超过depth[x]+d的节点的颜色数量,强制在线.(n,m<=100000,多组数据,保证n,m总和不超过5 ...
- bzoj省选十连测推广赛
A.普通计算姬 题意:给丁一棵树,每个点有一个权值,用sum(x)表示以x为根的子树的权值和,要求支持两种操作: 1 u v :修改点u的权值为v. 2 l r : 求∑sum[i] l&l ...
- [BZOJ]2017省队十连测推广赛1
听学长说有比赛就随便打一打. A.普通计算姬 题目大意:给出一棵带权树,支持一下两种操作:1.修改一个点的权值:2.给出l,r,询问以点l为根的子树和.点l+1为根的子树和.点l+2为根的子树和--点 ...
- 【省选十连测之九】【DP】【组合计数去重】【欧拉函数】基本题
目录 题意: 输入格式: 输出格式: 数据范围: 思路: 嵌套题的转移 基本题的转移 Part1 Part2 Part3 代码 题意: 这是一个关于括号组合的题. 首先定义一道题是由'(',')',' ...
- 【省选十连测之一】【线段树】【最小生成树之Kruskal】公路建设
目录 题意 输入格式 输出格式 数据范围 思路 代码 题意 有n个点,m条双向道路,其中第条公路的两个端点是u[i],v[i],费用是c[i]. 现在给出q个询问,每次给定一个L和一个R,要求你只能够 ...
- 【正睿oi省选十连测】第一场
四小时写了两个暴力??自闭 [原来这就是神仙们的分量Orz rank 56/75 可以说是无比垃圾了 下周目标:进步十名?[大雾 T1 题意:有n个点的图 点有点权Ai 也有点权Bi = A_1 + ...
- bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树
[Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 93 Solved: 53[Submit][Status][ ...
- bzoj 5216: [Lydsy2017省队十连测]公路建设
5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 66 Solved: 37[Submit][St ...
- ZROI2019 提高十连测
额 掰手指头一数 特么又是第三年十连测了= = 2017一场没打 那时候好像一场比赛也就100人左右 2018前几场还都好好补了 后来开始放飞自我了 这时候一场有150人还多了 2019想让今年的No ...
随机推荐
- TortoiseGit安装与使用
公司的源码是在码云上,平时进行项目源码管理和团队开发都会使用到GIT,花了一天时间才将Git搞明白,这是一个工具,我在这里就简单说一下,其安装使用方法,也是对自己学习的总结;本文章适合于刚接触GIT的 ...
- SpringBoot单元测试中的事务和Session
1.Springboot中使用junit编写单元测试,并且测试结果不影响数据库. 2.
- maven入门(1-3)构建简单的maven项目
1. 用Maven 命令创建一个简单的Maven项目 在cmd中运行如下命令: mvn archetype:generate -DgroupId=com.mycompany.app -Dartifac ...
- EasyUI中datagrid的基本用法
EasyUI中datagrid是最常用的一个控件了,现在整理一下datagrid的基本语法,先展示下页面效果吧,如下图
- 用Jmeter实现SQLServer数据库的增删查改
1.添加线程组 Jmeter性能测试,最重要的就是线程组了,线程组相当于用户活动 2.添加JDBC Connection Configuration Database URL:jdbc:sqlserv ...
- Linux系统的基本使用
曾经在网上看到一个一篇文章,说到了Linux学习的入门与学习技巧,也就是:初学者可以自己安装虚拟机,然后把linux常用命令例如cd.ls.chmod.useradd.vi等等多练习几十遍,把自己敲打 ...
- Qt自定义控件
Qt创建自定义控件教程 一.新建Qt设计师控件 二.设置项目名称 三.选择kits 这里取消Debug选项,不需要这个选项都是编译为dll文件直接调用. 删除掉MyControl原有的.h和cpp文件 ...
- Linux:crontab组件部署linux定时任务
crontab简介 crond 是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务 工具,并且会自动启动c ...
- Python:使用youtube-dl+ffmpeg+FQ软件下载youtube视频
声明:本文所述内容都是从http://blog.csdn.net/u011475134/article/details/71023612博文中学习而来. 背景: 一同学想通过FQ软件下载一些youtu ...
- [转][scrapy] CannotListenError: Couldn’t listen on [Errno 98] Address already in use.
[scrapy] CannotListenError: Couldn't listen on [Errno 98] Address already in use. python eason 1年前 ...