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序+线段树的更多相关文章

  1. Codeforces 396C (DFS序+线段树)

    题面 传送门 题目大意: 给定一棵树,每个点都有权值,边的长度均为1,有两种操作 操作1:将节点u的值增加x,并且对于u的子树中的任意一个点v,将它的值增加x-dist(u,v)*k, dist(u, ...

  2. Codeforces 1110F(DFS序+线段树)

    题面 传送门 分析 next_id = 1 id = array of length n filled with -1 visited = array of length n filled with ...

  3. Codeforces 1132G(dfs序+线段树)

    题面 传送门 分析 对于每一个数a[i],找到它后面第一个大于它的数a[p],由p向i连边,最终我们就会得到一个森林,且p是i的父亲.为了方便操作,我们再增加一个虚拟节点n+1,把森林变成树. 由于序 ...

  4. 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 ...

  5. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  6. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  7. 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 ...

  8. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  9. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

随机推荐

  1. zookeeper之一 安装和配置(单机+集群)

    这里我以zookeeper3.4.10.tar.gz来演示安装,安装到/usr/local/soft目录下. 一.单机版配置 1.安装和配置 #.下载 wget http://apache.fayea ...

  2. 题解 P1587 【[NOI2016]循环之美】

    知识点:莫比乌斯反演 积性函数 杜教筛 废话前言: 我是古明地恋,写这篇题解的人已经被我 请各位读者自行无视搞事的恋恋带有删除线的内容,谢谢茄子. 这道题目本身并不难,但是公式推导/代码过程中具有迷惑 ...

  3. SSM整合中错误:Data truncation: Data too long for column 'gender' at row 1

    错误描述 ### SQL: insert into t_customer(name,gender,phone,address) values (?,?,?,?) ### Cause: com.mysq ...

  4. docker for windows 中 镜像 microsoft/donet 的文件结构

    一共有3个文件夹和1个文件: [Program Files] [Users] [Windows] License.txt 使用vs默认生成的dockerfile文件生成后,会新增app文件夹.

  5. redis过期策略设置

    中6中过期策略的具体方式. redis 中的默认的过期策略是volatile-lru .设置方式 可以通过命令直接设置 config set maxmemory-policy volatile-lru ...

  6. Seata简单介绍及其原理(一)

    Seata 是什么? Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的 ...

  7. Codeforces Round #350(Div 2)

    因为当天的下午才看到所以没来得及请假所以这一场没有打...于是信息课就打了这场的模拟赛. A题: *题目描述: 火星上的一年有n天,问每年最少和最多有多少休息日(周六周天). *题解: 模7分类讨论一 ...

  8. Android使用命令行操作数据库

    所有的应用程序本地文件都存放在/data/data/目录下 C:\Users\nicole>adb shell * daemon not running. starting it now on ...

  9. 大数据笔记(五)——HDFS的高级特性

    一.HDFS的回收站: recyclebin 1.HDFS的回收站默认是关闭的 2.启用回收站:去core-site.xml配置 路径:/root/training/hadoop-2.7.3/etc/ ...

  10. kvm中添加VNC密码

      #virsh edit 虚机名 <graphics type='vnc' port='5901' autoport='no' listen='0.0.0.0' keymap='en-us'/ ...