hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:
给出一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
分析:
典型的树链剖分,对节点进行操作,可以用树状数组或者线段树。
树链剖分+树状数组:
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstring>
- using namespace std;
- const int maxn = ;
- struct Edge
- {
- int to,next;
- }edge[maxn*];
- int head[maxn],cnt,num;
- int a[maxn],n,m,p,c[maxn];
- int size[maxn],top[maxn],id[maxn],fa[maxn],son[maxn],dep[maxn];
- void init()
- {
- memset(head,-,sizeof(head));
- memset(son,-,sizeof(son));
- memset(c,,sizeof(c));
- cnt=;
- num=;
- }
- void addedge(int u,int v)
- {
- edge[cnt].to = v;
- edge[cnt].next = head[u];
- head[u] = cnt++;
- }
- void dfs_1(int u,int f,int d)
- {
- dep[u]=d;
- size[u]=;
- fa[u]=f;
- for(int i=head[u];i!=-;i=edge[i].next)
- {
- int v=edge[i].to;
- if(v==f)
- continue;
- dfs_1(v,u,d+);
- size[u]+=size[v];
- if(son[u]==-||size[son[u]]<size[v])
- son[u]=v;
- }
- }
- void dfs_2(int u,int tp)
- {
- top[u] = tp;
- id[u] = ++num;
- if(son[u]!=-)
- dfs_2(son[u],tp);
- for(int i=head[u];i!=-;i=edge[i].next)
- {
- int v=edge[i].to;
- if(v==fa[u]||v==son[u])
- continue;
- dfs_2(v,v);
- }
- }
- int lowbit(int x)
- {
- return x&-x;
- }
- int sum(int x)
- {
- int res=;
- while(x>)
- {
- res+=c[x];
- x-=lowbit(x);
- }
- return res;
- }
- void add(int x,int d)
- {
- while(x<=n)
- {
- c[x]+=d;
- x+=lowbit(x);
- }
- }
- void change(int u,int v,int val)
- {
- int tp1=top[u],tp2=top[v];
- while(tp1!=tp2)
- {
- if(dep[tp1]<dep[tp2])
- {
- swap(tp1,tp2);
- swap(u,v);
- }
- add(id[tp1],val);
- add(id[u]+,-val);
- u=fa[tp1];
- tp1=top[u];
- }
- if(dep[u]>dep[v])
- swap(u,v);
- add(id[u],val);
- add(id[v]+,-val);
- }
- int main()
- {
- while(~scanf("%d%d%d",&n,&m,&p))
- {
- init();
- for(int i=;i<=n;i++)
- scanf("%d",&a[i]);
- for(int i=;i<=m;i++)
- {
- int u,v;
- scanf("%d%d",&u,&v);
- addedge(u,v);
- addedge(v,u);
- }
- dfs_1(,,);
- dfs_2(,);
- for(int i=;i<=n;i++)
- {
- add(id[i],a[i]);
- add(id[i]+,-a[i]);
- }
- char s[];
- int c1,c2,k,c;
- for(int i=;i<p;i++)
- {
- scanf("%s",s);
- if(s[]=='I')
- {
- scanf("%d%d%d",&c1,&c2,&k);
- change(c1,c2,k);
- }
- if(s[]=='D')
- {
- scanf("%d%d%d",&c1,&c2,&k);
- change(c1,c2,-k);
- }
- if(s[]=='Q')
- {
- scanf("%d",&c);
- cout<<sum(id[c])<<endl;
- }
- }
- }
- return ;
- }
树链剖分+线段树:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<cmath>
- using namespace std;
- const int maxn = ;
- int n,m,p;
- int val[maxn],a[maxn];
- struct Edge
- {
- int to,next;
- }edge[maxn*];
- int head[maxn],add[maxn*];
- int dep[maxn],fa[maxn],size[maxn],son[maxn],top[maxn],id[maxn];
- int cnt,num;
- void init()
- {
- memset(head,-,sizeof(head));
- memset(son,-,sizeof(son));
- memset(add,,sizeof(add));
- cnt=;
- num=;
- }
- void addedge(int u,int v)
- {
- edge[cnt].to=v;
- edge[cnt].next=head[u];
- head[u]=cnt++;
- }
- void dfs_1(int u,int f,int d)
- {
- dep[u]=d;
- size[u]=;
- fa[u]=f;
- for(int i=head[u];i!=-;i=edge[i].next)
- {
- int v=edge[i].to;
- if(v==f)
- continue;
- dfs_1(v,u,d+);
- size[u]+=size[v];
- if(son[u]==-||size[son[u]]<size[v])
- son[u]=v;
- }
- }
- void dfs_2(int u,int tp)
- {
- top[u] = tp;
- id[u] = ++num;
- if(son[u]!=-)
- dfs_2(son[u],tp);
- for(int i=head[u];i!=-;i=edge[i].next)
- {
- int v = edge[i].to;
- if(v == fa[u] ||v == son[u])
- continue;
- dfs_2(v,v);
- }
- }
- struct Tree
- {
- int left,right;
- int sum;
- }tree[maxn*];
- void pushup(int i)
- {
- tree[i].sum = tree[i*].sum + tree[i*+].sum;
- }
- void build(int i,int begin,int end)
- {
- tree[i].left=begin;
- tree[i].right=end;
- if(begin==end)
- {
- tree[i].sum=val[begin];
- return;
- }
- int mid=(begin+end)/;
- build(i*,begin,mid);
- build(i*+,mid+,end);
- pushup(i);
- }
- void pushdown(int i)
- {
- if(add[i])
- {
- add[i*] += add[i];
- add[i*+] += add[i];
- int mid=(tree[i].left+tree[i].right)/;
- tree[i*].sum += add[i]*(mid-tree[i].left+);
- tree[i*+].sum += add[i]*(tree[i].right-mid);
- add[i]=;
- }
- }
- void update(int i,int begin,int end,int value)
- {
- if(tree[i].left>=begin&&tree[i].right<=end)
- {
- add[i]+=value;
- tree[i].sum+=value*(tree[i].right-tree[i].left+);
- return;
- }
- pushdown(i);
- int mid=(tree[i].left+tree[i].right)/;
- if(mid>=begin)
- update(i*,begin,end,value);
- if(mid<end)
- update(i*+,begin,end,value);
- pushup(i);
- }
- void change(int u,int v,int value)
- {
- int tp1=top[u],tp2=top[v];
- while(tp1!=tp2)
- {
- if(dep[tp1]<dep[tp2])
- {
- swap(tp1,tp2);
- swap(u,v);
- }
- update(,id[tp1],id[u],value);
- u = fa[tp1];
- tp1 = top[u];
- }
- if(dep[u]>dep[v])
- swap(u,v);
- update(,id[u],id[v],value);
- }
- long long query(int i,int begin,int end)
- {
- if(tree[i].left>=begin&&tree[i].right<=end)
- return tree[i].sum;
- pushdown(i);
- int mid=(tree[i].left+tree[i].right)/;
- long long ans=;
- if(mid>=begin)
- ans+=query(i*,begin,end);
- if(mid<end)
- ans+=query(i*+,begin,end);
- return ans;
- }
- int main()
- {
- while(~scanf("%d%d%d",&n,&m,&p))
- {
- init();
- for(int i=;i<=n;i++)
- scanf("%d",&a[i]);
- for(int i=;i<=m;i++)
- {
- int u,v;
- scanf("%d%d",&u,&v);
- addedge(u,v);
- addedge(v,u);
- }
- dfs_1(,,);
- dfs_2(,);
- for(int i=;i<=n;i++)
- val[id[i]]=a[i];
- build(,,n);
- char s[];
- int c1,c2,k,c;
- for(int i=;i<p;i++)
- {
- scanf("%s",s);
- if(s[]=='I')
- {
- scanf("%d%d%d",&c1,&c2,&k);
- change(c1,c2,k);
- }
- if(s[]=='D')
- {
- scanf("%d%d%d",&c1,&c2,&k);
- change(c1,c2,-k);
- }
- if(s[]=='Q')
- {
- scanf("%d",&c);
- cout<<query(,id[c],id[c])<<endl;
- }
- }
- }
- return ;
- }
hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)的更多相关文章
- Qtree3题解(树链剖分(伪)+线段树+set)
外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
- 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树
题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- 刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)
题目: Description 在一片古老的土地上,有一个繁荣的文明. 这片大地几乎被森林覆盖,有N座城坐落其中.巧合的是,这N座城由恰好N-1条双 向道路连接起来,使得任意两座城都是连通的.也就是说 ...
- BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树
题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
[BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...
- bzoj3531——树链剖分+动态开点线段树
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连 ...
随机推荐
- Effective Objective-C 2.0 Tips 总结 Chapter 3 & Chapter 4
Chapter 3 接口与 API 设计 Tips 15 使用前缀避免明明空间冲突 Objective-C 没有命名空间,所以我们在起名时要设法避免命名冲突 避免命名冲突的方法就是使用前缀 应用中的所 ...
- 关于移动端自动化测试-Appium的搭建
web端我们常用的开源自动化用的是selenium,而移动端我们选择的是Appium,当然也可以使用monkey或者阿里的macaca,他们在理论上都使用了webdriver: 关于Appium环境的 ...
- Angular02 将数据添加到组件中
准备:已经搭建好angular-cli环境.知道如何创建组件 一.将一个数据添加到组件中 1 创建一个新的组件 user-item 2 将组件添加到静态模板中 3 为组件添加属性,并利用构造器赋值 4 ...
- (转)CentOS6.5下Redis安装与配置
场景:项目开发中需要用到redis,之前自己对于缓存这块一直不是很理解,所以一直有从头做起的想法. 本文详细介绍redis单机单实例安装与配置,服务及开机自启动.如有不对的地方,欢迎大家拍砖o(∩_∩ ...
- (转)Windows7下命令行使用MySQL
1 安装 我在Win7下安装的MySQL版本是mysql-5.0.22-win32 1.在Win7环境下安装MySQL,关于安装方法可以参考文章: Win7系统安装MySQL5.5.21图解教程.wi ...
- Spring源码情操陶冶-ContextLoader
前言-阅读源码有利于陶冶情操,本文承接前文Spring源码情操陶冶-ContextLoaderListener 静态代码块内容 ContextLoader在被主动调用的时候,会执行其的一个静态块,代码 ...
- 前端javascript中字符串的总结
1.截取方法 截取字符串的abcdefg中的efg. 注意:str.length从1的开始数 var str="abcdefg"; (1).slice() : console.lo ...
- 解决div里面img的缝隙问题(转)
图片IMG与容器下边界之间有空隙怎么办?这里介绍3中简单的解决方法. 第一,给图片img标签display:block. img{display:block} 第二,定义容器里的字体大小为0. div ...
- vue中watched属性
watched属性,vue中的观察属性,可用来监听一个值的变化 默认有两个参数,新值,旧值 data (){ return { currentCity: "深圳" } } watc ...
- Mybatis 的分页条件查询语句编写
刚来到一家新公司, 翻看项目代码, 发现一位同事写的查询逻辑很好, 不用插件, 一个语句完成了分页条件查询. 而我之前一般都是在业务层对参数进行判断, 如果有条件,就调用条件查询的方法, 如果没有条件 ...