CodeForces 877E DFS序+线段树
CodeForces 877E DFS序+线段树
题意
就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身一共有几个灯是亮的。pow x,表示你需要改变x的子树和x本身上的灯的状态。
题解思路
这个题肯定是用DFS序了,为啥?因为树不好操作啊(我也不会啊),使用DFS序可以把树压成一维的一串数,这样就可以使用线段树来进行区间操作了。
话说这个题是我暑假限时训练中做的,看到这个题老开心了,但是让我万万没想到的是,这个题我交了11次才过,太心酸了。
代码实现
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<vector>
using namespace std;
const int maxn=2e5+100;
struct node{
int l, r;
int sum;
int lazy;
}t[maxn<<2];
vector<int> g[maxn];
int num[maxn];
int in[maxn], out[maxn], rk[maxn], cnt;
int n, m;
void dfs(int u, int fa) //
{
in[u]=++cnt;//这个是u进去的是时间
rk[cnt]=u; //不要忘了这个,这个是新生成的序列,也就是树被压成一维的那个数列。就是这忘了,害的我好苦。
int len=g[u].size();
for(int i=0; i<len; i++)
{
int v=g[u][i];
if(v==fa) continue;
dfs(v, u);
}
out[u]=cnt;
}
void up(int rt)
{
t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;
}
void build(int rt, int l, int r)
{
t[rt].l=l;
t[rt].r=r;
t[rt].sum=0;
t[rt].lazy=0;
if(l==r)
{
t[rt].sum=num[rk[l]]; //这里也不要能错了,很重要。
return ;
}
int mid=(l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
up(rt);
}
void down(int rt)
{
if(t[rt].lazy==0) return ;
int ls=rt<<1, rs=rt<<1|1;
t[ls].lazy=!t[ls].lazy;
t[ls].sum=t[ls].r-t[ls].l+1-t[ls].sum;
t[rs].lazy=!t[rs].lazy;
t[rs].sum=t[rs].r-t[rs].l+1-t[rs].sum;
t[rt].lazy=0;
}
void update(int rt, int l, int r)
{
if(l <= t[rt].l && t[rt].r <= r )
{
t[rt].lazy = !t[rt].lazy;
t[rt].sum=t[rt].r-t[rt].l+1-t[rt].sum;
return ;
}
down(rt);
int mid=(t[rt].l+t[rt].r)>>1;
if(l<=mid) update(rt<<1, l, r);
if(r>mid) update(rt<<1|1, l, r);
up(rt);
}
int query(int rt, int l, int r)
{
if(l <= t[rt].l && t[rt].r <= r)
{
return t[rt].sum;
}
int ans=0;
down(rt);
int mid=(t[rt].l+t[rt].r)>>1;
if(l<=mid) ans+=query(rt<<1, l, r);
if(r>mid) ans+=query(rt<<1|1, l, r);
return ans;
}
void init()
{
cnt=0;
for(int i=0; i<=n; i++)
{
g[i].clear();
}
}
int main()
{
scanf("%d", &n);
{
cnt=0;
int x;
string op;
if(n==1)
{
scanf("%d", &x);
scanf("%d" , &m);
while(m--)
{
int tmp;
cin>>op;
scanf("%d", &tmp);
if(op=="get") printf("%d\n", x);
else x=!x;
}
return 0;
}
for(int i=2; i<=n; i++)
{
scanf("%d", &x);
g[x].push_back(i);
g[i].push_back(x);
}
dfs(1, 0);
for(int i=1; i<=n; i++)
{
scanf("%d", &num[i]);
}
build(1, 1, n);
scanf("%d", &m);
for(int i=1; i<=m; i++)
{
cin>>op;
scanf("%d", &x);
if(op=="get")
{
printf("%d\n", query(1, in[x], out[x]));
}
else
{
update(1, in[x], out[x]);
}
}
}
return 0;
}
CodeForces 877E DFS序+线段树的更多相关文章
- Codeforces 396C (DFS序+线段树)
题面 传送门 题目大意: 给定一棵树,每个点都有权值,边的长度均为1,有两种操作 操作1:将节点u的值增加x,并且对于u的子树中的任意一个点v,将它的值增加x-dist(u,v)*k, dist(u, ...
- Codeforces 1110F(DFS序+线段树)
题面 传送门 分析 next_id = 1 id = array of length n filled with -1 visited = array of length n filled with ...
- Codeforces 1132G(dfs序+线段树)
题面 传送门 分析 对于每一个数a[i],找到它后面第一个大于它的数a[p],由p向i连边,最终我们就会得到一个森林,且p是i的父亲.为了方便操作,我们再增加一个虚拟节点n+1,把森林变成树. 由于序 ...
- CodeForces 877E Danil and a Part-time Job(dfs序+线段树)
Danil decided to earn some money, so he had found a part-time job. The interview have went well, so ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
随机推荐
- 安装php-solr扩展
本人qq群也有许多的技术文档,希望可以为你提供一些帮助(非技术的勿加). QQ群: 281442983 (点击链接加入群:http://jq.qq.com/?_wv=1027&k=29Lo ...
- #pragma 的使用(转)
尽管 C 和 C++ 都已经有标准,但是几乎每个编译器 (广义,包含连接器等) 扩展一些 C/C++ 关键字. 合理地应用这些关键字,有时候能使我们的工作非常方便.下面随便说说 Visual C++ ...
- [CF1208D] Restore Permutation
传送门 题意:有一个长为\(n\)的排列\(p\),设\(S_i=\sum_{j=1}^{i-1}p_j\cdot[p_j<p_i]\),给出\(S\),要求还原出\(p\).保证有解,\(n\ ...
- JS 图片转blob 转base64
//转换为blob有跨域限制 var loadImageToBlob = function (url, callback) { if (!url || !callback) return false; ...
- Java使用wait() notify()方法操作共享资源详解_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方 ...
- Quick BI支持哪些数据源(配置操作篇)
Quick BI 潜心打造了核心技术底座(OLAP分析引擎),实现了SQL解析.SQL调度.SQL优化.查询加速等基础能力,支撑Quick BI的数据分析和查询加速.OLAP分析引擎包括数据源连接.数 ...
- js数字每3位加一个逗号
if(typeof val ==="number"){ var str = val.toString(); ? /(\d)(?=(\d{})+\.)/g : /(\d)(?=(?: ...
- [洛谷2257]ZAP-Queries 题解
前言 这道题还是比较简单的 解法 首先将题目转化为数学语言. 题目要我们求的是: \[\sum_{i=1}^a\sum_{j=1}^b[gcd(i,j)=d]\] 按照套路1,我们将其同时除以d转换为 ...
- js返回上一页并刷新的几种方法
1.返回上一页 1)<a href="javascript:history.go(-1)"></a> 2)<a href="javascri ...
- (转载)《利用Python进行数据分析·第2版》电子书
https://www.jianshu.com/p/04d180d90a3f https://www.jianshu.com/p/04d180d90a3f https://www.jianshu.co ...