[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 ...
随机推荐
- GIT入门笔记(12)- 删除文件、提交删除和恢复删除
在Git中,删除也是一个修改操作,我们实战一下, 1.先添加add一个新文件test.txt到Git并且提交commit到本地版本库: $ git add test.txt$ git commit - ...
- linux下安装 配置 redis数据库
通过终端命令安装(推荐): 1 确保更新源服务器能正常使用 如果没有更换更新源服务器,那么可能一直都下不了软件.欢迎参考我之前的博文来更换成国内的镜像服务器http://www.cnblogs.com ...
- Pymsql
Pymsql 1.创建数据库连接 pymsql connect conn=pymysql.connect(host="localhost",user="root" ...
- 浅析php过滤html字符串,防止SQL注入的方法
批量过滤post,get敏感数据 复制代码 代码如下: $_GET = stripslashes_array($_GET);$_POST = stripslashes_array($_POST); 数 ...
- [Micropython]TPYBoard v10x拼插编程实验 点亮心形点阵
一.什么是TPYBoard开发板 TPYBoard是以遵照MIT许可的MicroPython为基础,由TurnipSmart公司制作的一款MicroPython开发板,它基于STM32F405单片机, ...
- python3全栈开发-异常处理
一. 什么是异常 异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下 而错误分成两种 ...
- [LeetCode] IP to CIDR 将IP地址转为CIDR无类别域间路由
Given a start IP address ip and a number of ips we need to cover n, return a representation of the r ...
- [LeetCode] K Empty Slots K个空槽
There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one ...
- 重载运算符“ <<” 和“>>” 运算符
:" << " " >> " 的重载作为友元函数重载,有两种方法:1,把变量作为public,就可以不用友元声明:2,先友元声 ...
- [Codeforces 176B]Word Cut
Description 题库链接 给你两个字符串 \(S\) 和 \(T\) ,准许你 \(k\) 次操作,每次将字符串左右分成两个非空的部分,再交换位置,问你有多少种不同的操作方法将 \(S\) 串 ...