HDU3966(树链剖分) 模板题
2016-01-27 00:56
447 查看
呃…学习的话有个链接http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
(对没错,我就是来贴代码的…因为CF有道题要用树链剖分所以 学习了一下
(对没错,我就是来贴代码的…因为CF有道题要用树链剖分所以 学习了一下
[code]#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #include<queue> #include<stack> #include<string> #include<vector> #include<map> #include<set> using namespace std; #define rfor(i,a,b) for(i=a;i<=b;++i) #define lfor(i,a,b) for(i=a;i>=b;--i) #define sfor(i,a,h) for(i=h[a];i!=-1;i=e[i].next) #define mem(a,b) memset(a,b,sizeof(a)) #define mec(a,b) memcpy(a,b,sizeof(b)) #define cheak(i) printf("%d ",i) #define min(a,b) (a>b?b:a) #define max(a,b) (a>b?a:b) #define inf 0x3f3f3f3f #define lowbit(x) (x&(-x)) typedef long long LL; #define maxn 50010 #define maxm maxn*maxn #define lson(x) (splay[x].son[0]) #define rson(x) (splay[x].son[1]) int n,m,q,tim; int num[maxn],siz[maxn],top[maxn],son[maxn]; int dep[maxn],tid[maxn],Rank[maxn],fa[maxn]; struct node { int next,sta,to; }e[maxn*2]; int tot,h[maxn]; void add_edge(int a,int b) { e[++tot].next=h[a]; e[tot].sta=a; e[tot].to=b; h[a]=tot; } void init() { mem(h,-1);mem(son,-1); tim=0;tot=0; } //树链剖分 void dfs1(int u,int father,int d) { dep[u]=d;fa[u]=father; siz[u]=1; for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].to; if(v!=father) { dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { top[u]=tp;tid[u]=++tim; Rank[tim]=u; if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].to; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } } //segment struct Tree { int sum,col; }tree[maxn*4]; void Push_up(int index) { tree[index].sum=max(tree[index*2].sum,tree[index*2+1].sum); } void Push_down(int index,int k) { if(tree[index].col) { tree[index*2].col+=tree[index].col; tree[index*2+1].col+=tree[index].col; tree[index*2].sum+=(k-k/2)*tree[index].col; tree[index*2+1].sum+=(k/2)*tree[index].col; tree[index].col=0; } } void build(int l,int r,int index) { tree[index].col=0; if(l==r) { tree[index].sum=num[Rank[l]]; return ; } int mid=(l+r)/2; build(l,mid,index*2); build(mid+1,r,index*2+1); Push_up(index); } int query(int l,int r,int index,int val) { if(l==r) return tree[index].sum; Push_down(index,r-l+1); int mid=(l+r)/2; int ret=0; if(val<=mid) ret=query(l,mid,index*2,val); else ret=query(mid+1,r,index*2+1,val); Push_up(index); return ret; } void update(int L,int R,int val,int l,int r,int index) { if(L<=l&&R>=r) { tree[index].col+=val; tree[index].sum+=val*(r-l+1); return ; } Push_down(index,r-l+1); int mid=(l+r)/2; if(L<=mid) update(L,R,val,l,mid,index*2); if(R>mid) update(L,R,val,mid+1,r,index*2+1); Push_up(index); } void Change(int x,int y,int val) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); update(tid[top[x]],tid[x],val,1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); update(tid[x],tid[y],val,1,n,1); } int main() { int i,k,a,b,c; while(~scanf("%d%d%d",&n,&m,&k)) { init(); rfor(i,1,n) scanf("%d",&num[i]); rfor(i,1,m) { scanf("%d%d",&a,&b); add_edge(a,b);add_edge(b,a); } dfs1(1,0,0); dfs2(1,1); build(1,n,1); while(k--) { char oper[5]; scanf("%s",oper); if(oper[0]=='Q') { scanf("%d",&a); printf("%d\n",query(1,n,1,tid[a])); } else { scanf("%d%d%d",&a,&b,&c); if(oper[0]=='D') c=-c; Change(a,b,c); } } } return 0; }
相关文章推荐
- [ 备忘 ] php 正则表达式与 mysql IN 查询的排序问题
- [傅里叶变换及其应用学习笔记] 二十七. 高维傅里叶变换,复习
- fiddler抓包
- [ 笔记 ] PHP 命名空间(namespace)
- 20160126深入浅出obc知识点整理
- js正则表达式lastIndex
- MyEclipse 2015 Stable 1.0下载安装破解日志
- linux的一些常用命令和emacs的一些快捷键
- The Swift Programming Language阅读笔记
- Leetcode Largest Number
- Eclipse的基本设置
- Scrapy安装过程问题总结
- Mac下配置liteide
- GCC 编译详解
- 《编码隐藏在计算机软硬件背后的语言》读感
- Leetcode 187. Repeated DNA Sequences
- dubbo spi--实现细节
- poj3966
- 有关于Cocos2d-X的几个坑(2016.1.26)
- 背包问题