Qtree3题解(树链剖分+线段树+set)
外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的。看没有题解还是来一篇...
题意
很易懂吧。。
题解
我的做法十分的暴力:树链剖分(伪)+线段树+ std :: set ...
首先,我们可以考虑每次修改一个点的颜色的影响。
易知,翻转一个点颜色,只会对于他的子树产生影响,对于别的点就毫无意义了。
然后,只要学过一点树链剖分的就知道,我们可以将整棵树按它的\(dfs\)序进行标号,
每个点的序号就是\(dfn\),
然后记下它的子树大小\(size\),然后对于每个点\(u\)所在的子树区间就是\([dfn[u], dfn[u]+size[u]-1]\)。
所以每次操作的时候,只要对于那一段区间进行修改就行了。
然后我们要修改和查询什么呢?不就是查询包含这个点,且深度最小的黑点吗?(需要把\(1\)作为根)
所以,我们每次记下一个区间中,包含这个点的所有黑色标号以及他们的深度,用\(pair\)记录一下(因为这个可以
自动按照第一关键字排序),再用\(set\)维护一下区间最值就行了。
每次更新的时候只要在\(set\)里面\(insert\)和\(erase\)。
查询就是从根节点一直向下跑,不断取一个深度更小的\(ans\)。
具体有些实现在程序中会体现的……
总时间复杂度\(O(q \log \ n \log q)\) 空间复杂度也是\(O(q \log \ n \log \ q)\)。(所以说很暴力嘛……)
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(int i = (l), _end_ = (int)(r); i <= _end_; ++i)
#define Fordown(i, r, l) for(int i = (r), _end_ = (int)(l); i >= _end_; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar() ) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar() ) x = (x<<1) + (x<<3) + (ch ^ '0');
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("P4116.in", "r", stdin);
freopen ("P4116.out", "w", stdout);
#endif
}
const int N = 1e5 + 1e3, M = N << 1;
int n, q;
int sz[N], dfn[N], dep[N];
int to[M], Next[M], Head[N], e = 0;
void add(int u, int v) {
to[++e] = v;
Next[e] = Head[u];
Head[u] = e;
}
void Dfs(int u, int fa) {
static int clk = 0;
sz[u] = 1;
dfn[u] = ++ clk;
dep[u] = dep[fa] + 1;
for (register int i = Head[u]; i; i = Next[i]) {
register int v = to[i];
if (v == fa) continue ;
Dfs(v, u); sz[u] += sz[v];
}
}//就是树链剖分的第一个dfs,求出size,dep,dfn
typedef pair<int, int> PII;
#define mp make_pair
#define lson o << 1, l, mid
#define rson o << 1 | 1, mid + 1, r
set<PII> S[N << 2];
bool col[N];//因为不知道是变啥颜色,所以要记一下原来的颜色
bool uopt; int ul, ur; PII uv;
void Update(int o, int l, int r) {
if (ul <= l && r <= ur) {
if (uopt) S[o].erase(uv);
else S[o].insert(uv);
//erase可以直接调用那个值.
return ;
}
int mid = (l + r) >> 1;
if (ul <= mid) Update(lson);
if (ur > mid) Update(rson);
}
PII ans; int up;
void Query(int o, int l, int r) {
if ((bool)S[o].size() )
ans = min(ans, *S[o].begin() );
//begin就是这个set中最小的那一个,即这里面深度最小的那个点
if (l == r) return ;
int mid = (l + r) >> 1;
if (up <= mid) Query(lson);
else Query(rson);
}
const int inf = 0x3f3f3f3f;
int main () {
n = read(); q = read();
For (i, 1, n - 1) {
int u, v;
scanf ("%d%d", &u, &v);
//int u = read(), v = read();
add(u, v); add(v, u);
}
Dfs(1, 0);
For (i, 1, q) {
int opt, pos;
scanf ("%d%d", &opt, &pos);
//int opt = read(), pos = read();
if (opt == 0) {
uopt = col[pos];
col[pos] ^= true;
ul = dfn[pos];
ur = dfn[pos] + sz[pos] - 1;
uv = mp(dep[pos], pos);
Update(1, 1, n);
} else {
ans = mp(inf, inf);
up = dfn[pos];
Query(1, 1, n);
printf ("%d\n", ans.second == inf ? -1 : ans.second);
}
}
//cerr << clock() << endl;
return 0;
}
后记:看到很多dalao都是用啥 主席树,倍增,和不用\(set\)的线段树做过去的。跑得都比我快,希望后面有人能讲一讲QAQ。
Qtree3题解(树链剖分+线段树+set)的更多相关文章
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp
题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...
- 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp
题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...
- 2243: [SDOI2011]染色 树链剖分+线段树染色
给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...
- 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分
题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...
随机推荐
- Postgres使用ALTER USER命令修改用户的密码、密码过期,锁定,解锁
使用ALTER USER命令修改用户的密码.密码过期,锁定,解锁 (1)修改用户的口令,将用户的口令修改为新的密码 highgo=#create user test with password ‘te ...
- JQuery_自带的动画效果
1.方法: show:显示选中元素. hide:隐藏选中元素. toggle:显示或隐藏选中元素. fadeIn:将选中元素的不透明度逐步提升到100%. fadeOut:将选中元素的不透明度逐步降为 ...
- Matlab入门笔记(1)
1.简单练习题: cos(((1+2+3+4+5)^3/5)^0.5) sin(pi^0.5)+log(tan(1)) 2^(3.5*1.7) exp(sin(10)) 2.实数,复数,行向量,列向量 ...
- Redis哨兵模式(sentinel)学习总结及部署记录(主从复制、读写分离、主从切换)
Redis的集群方案大致有三种:1)redis cluster集群方案:2)master/slave主从方案:3)哨兵模式来进行主从替换以及故障恢复. 一.sentinel哨兵模式介绍Sentinel ...
- Oracle的安装与配置
好久不来博客园了,有种熟悉而又陌生的感觉. 今天我装一下Oracle数据库,从头开始,因为昨天在虚拟机装了,不能用,卸掉了,系统也卸掉了,今天重新装,包括系统. 系统装好了,Oracle准备好了. 这 ...
- mybatis中批量更新的问题
问题:使用mybatis在执批量更新操作时,一直报错执行失败 解决方法: 首先打印了SQL语句,发现SQL语句拿出来执行没问题,也可以批量执行.SQL没问题,应该是配置的问题. 在网上查询和很多资料, ...
- 第三个Sprint ------第十天
上传到Github github 地址:https://github.com/be821/MyCat 百度云盘: 链接: http://pan.baidu.com/s/1hrxL6lu 密码: k9t ...
- 第二个spring
由于第一个spring已经完成,我们现在进去第二个spring! 陈志棚:成绩的统筹 李天麟:界面音乐 徐侃:代码算法 plan好布局,分配任务,控制时间!
- maven配置私服
1先配置maven的配置文件 2在项目的pom.xml文件增加 <distributionManagement> <repository> <id>nexus-re ...
- wordpress升级出错
服务器是腾讯云 搜索到的解决方案有几个,试了好几个,不知道哪个是根本原因,反正都操作了. 设置wordpress文件夹和子文件夹的权限 编辑wp-config.php,在文末添加如下: define( ...