[Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]
题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空。注意边界,编号是从0开始的,容易漏掉树根。
第一次写树剖~
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 9 using namespace std; 10 11 struct Edge 12 { 13 int to,next; 14 }e[210000]; 15 16 int ind,n,Pre[210000],f[810000],Sum[810000],Out_dfn[210000]; 17 int p[210000],cnt,hv[210000],Head[210000],Dfn[210000]; 18 19 void Add_edge(const int & x,const int & y) 20 { 21 e[++cnt].to=y; 22 e[cnt].next=p[x]; 23 p[x]=cnt; 24 return ; 25 } 26 27 int Init_Dfs(const int& S) 28 { 29 int num=1,i,Max_=0; 30 for(i=p[S];i;i=e[i].next) 31 { 32 int temp=Init_Dfs(e[i].to); 33 if(temp>Max_)Max_=temp,hv[S]=e[i].to; 34 num+=temp; 35 } 36 return num; 37 } 38 39 void Dfs(const int& S,const int& fa) 40 { 41 int i; 42 if(!Head[S])Head[S]=Head[fa];Dfn[S]=++ind; 43 44 if(hv[S])Dfs(hv[S],S); 45 for(i=p[S];i;i=e[i].next) 46 { 47 if(e[i].to!=hv[S]) 48 { 49 Head[e[i].to]=e[i].to; 50 Pre[e[i].to]=S; 51 Dfs(e[i].to,S); 52 } 53 } 54 Out_dfn[S]=ind; 55 return ; 56 } 57 58 inline void push_down(const int & num,const int & l,const int & r) 59 { 60 if(f[num]) 61 { 62 if(l!=r) 63 { 64 f[num<<1]=f[num<<1|1]=f[num]; 65 } 66 if(f[num]==1)Sum[num]=r-l+1; 67 if(f[num]==-1)Sum[num]=0; 68 f[num]=0; 69 } 70 return ; 71 } 72 73 void push_up(const int & num,const int & l,const int & r) 74 { 75 if(l!=r) 76 { 77 int mid=l+((r-l)>>1); 78 push_down(num<<1,l,mid); 79 push_down(num<<1|1,mid+1,r); 80 Sum[num]=Sum[num<<1]+Sum[num<<1|1]; 81 } 82 return ; 83 } 84 85 void Change(const int & l,const int & r,const int & num, 86 const int & s,const int & t,const int &d) 87 { 88 if(s<=l && r<=t) 89 { 90 f[num]=d; 91 push_down(num,l,r); 92 return ; 93 } 94 int mid=l+((r-l)>>1); 95 push_down(num,l,r); 96 if(s<=mid)Change(l,mid,num<<1,s,t,d); 97 if(t>mid) Change(mid+1,r,num<<1|1,s,t,d); 98 push_up(num,l,r); 99 return ; 100 } 101 102 int Query(const int & l,const int & r,const int & num, 103 const int & s,const int & t) 104 { 105 if(s<=l && r<=t) 106 { 107 push_down(num,l,r); 108 return Sum[num]; 109 } 110 111 int mid=l+((r-l)>>1),temp=0; 112 push_down(num,l,r); 113 if(s<=mid)temp+=Query(l,mid,num<<1,s,t); 114 if(t>mid) temp+=Query(mid+1,r,num<<1|1,s,t); 115 push_up(num,l,r); 116 return temp; 117 } 118 119 int Get_sum_install(const int& S) 120 { 121 int x=S,temp=0,sum=0; 122 123 while(x) 124 { 125 sum+=Query(1,n,1,Dfn[Head[x]],Dfn[x]); 126 Change(1,n,1,Dfn[Head[x]],Dfn[x],1); 127 temp+=Dfn[x]-Dfn[Head[x]]+1; 128 x=Pre[Head[x]]; 129 } 130 131 return temp-sum; 132 } 133 134 int Get_sum_remove(const int & S) 135 { 136 int x=S,sum=0; 137 138 sum=Query(1,n,1,Dfn[x],Out_dfn[x]); 139 Change(1,n,1,Dfn[x],Out_dfn[x],-1); 140 141 return sum; 142 } 143 144 int main() 145 { 146 147 int i,x,q; 148 char op[15]; 149 150 scanf("%d",&n); 151 for(i=2;i<=n;++i) 152 { 153 scanf("%d",&x);x++; 154 Add_edge(x,i); 155 } 156 157 Init_Dfs(1); 158 159 Head[1]=1; 160 Dfs(1,1); 161 scanf("%d",&q); 162 for(i=1;i<=q;++i) 163 { 164 scanf("%s%d",op,&x);x++; 165 if(op[0]=='i') 166 printf("%d\n",Get_sum_install(x)); 167 else 168 printf("%d\n",Get_sum_remove(x)); 169 } 170 171 return 0; 172 }
View Code
不知道为什么,BZOJ TLE了,但是UOJ AC(求大神指教)??
转载于:https://www.cnblogs.com/Gster/p/4977886.html
[Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]相关推荐
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MB Submit: 1153 Solved: 421 [Submit][Sta ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)
题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...
- CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)
题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...
- P2486 [SDOI2011]染色(树链剖分+线段树)
题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...
- BZOJ4127Abs——树链剖分+线段树
题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- YbtOJ-染色计划【树链剖分,线段树,tarjan】
正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...
最新文章
- stm32编译时报错 ..........ER_IROM1: File exists 的问题
- ServletContextListener在Tomcat中的配置问题
- Problem A: 童年生活二三事
- Java calendar加减时间
- RenderHogs for Mac(ae禁用不必要的图层和效果提高渲染预览速度插件)
- 小汤学编程之JavaScript学习day01——认识JS、JS基础语法
- python模拟登陆 验证码el_8-python模拟登入(无验证码)
- 方法和函数有什么区别?
- java各种加密算法_Java中的各种加密算法
- BLE蓝牙4.0串口调试助手
- 传智黑马java基础学习——day14
- 光伏发电系统红外热图像(227幅图像,无标签,可用于识别蜗牛尾迹与热点故障)
- 平安人寿优+计划广纳英才,平安代理人实现职涯发展
- linux开机启动grub rescue,Ubuntu 开机出现 grub rescue 的模式下修复
- 跨越opengl和d3d的鸿沟(四):完结篇,平台和未来
- 顶象App加固——助力微投证券融入IOS生态
- 概率 插空法和捆绑法
- HelloWorld--JAVA程序
- ASP.NET程序设计教程(C#版)——学习心得
- 《你一年的8760小时》读后感