hdu3966(树链剖分)
update: 2018-01-27
下面的应该是很久之前抄的代码了,,当时应该是费了很大劲弄明白了一点吧=_=||
最近一直再刷数据结构,今天终于刷到树链剖分了,看了一下代码感觉挺清晰的...
具体讲解就看高级数据结构这本书吧,p401,感觉写的很清晰易懂。
最近几天最大的感受就是,半年前怎么都搞不明白的东西现在可以轻轻松松看懂了。我想可能就是当时这些东西确实超出了我的理解能力吧,其实后来这半年感觉并没有什么进步,应该就是不知不觉中提升了吧,忽然想起来半年前去看一年前的东西也是一样的感觉。
集训不剩几天了,之后还有别的事情要做呢,加油吧~
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3966
参考:http://blog.csdn.net/acdreamers/article/details/10594121
明天再补代码,,睡觉!!
----------------------------------------------------------------------------------
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 const int maxn=50010; 7 8 struct edge 9 { 10 int v,nex; 11 }e[maxn<<1]; 12 13 int n,m,q; 14 int cur; 15 int w[maxn],siz[maxn],top[maxn],son[maxn]; 16 // 节点权重 子树节点数 链首 重儿子 17 int dep[maxn],f[maxn],order[maxn],tid[maxn]; 18 // 深度 父亲 生成线段 遍历序列编号 19 20 int head[maxn]; 21 int cnt; 22 23 void init() 24 { 25 memset(head,-1,sizeof(head)); 26 memset(son,-1,sizeof(son)); 27 cur=0; 28 cnt=0; 29 } 30 31 void adde(int u,int v) 32 { 33 e[cnt].v=v; 34 e[cnt].nex=head[u]; 35 head[u]=cnt++; 36 } 37 38 39 40 //树链剖分 41 void dfs1(int u,int fa,int d) 42 { 43 dep[u]=d; 44 f[u]=fa; 45 siz[u]=1; 46 for(int i=head[u];i!=-1;i=e[i].nex) 47 { 48 int v=e[i].v; 49 if(v!=fa) 50 { 51 dfs1(v,u,d+1); 52 siz[u]+=siz[v]; 53 if(son[u]==-1||siz[v]>siz[son[u]]) //更新重儿子 54 son[u]=v; 55 } 56 } 57 } 58 59 void dfs2(int u,int tp) 60 { 61 top[u]=tp; 62 tid[u]=++cur; 63 order[tid[u]]=u; 64 if(son[u]==-1) return ; 65 dfs2(son[u],tp); 66 for(int i=head[u];i!=-1;i=e[i].nex) 67 { 68 int v=e[i].v; 69 if(v!=son[u]&&v!=f[u]) 70 dfs2(v,v); 71 } 72 } 73 74 //线段树 75 #define lson l,m,rt<<1 76 #define rson m+1,r,rt<<1|1 77 78 int sum[maxn<<2]; 79 int add[maxn<<2]; 80 81 void pushup(int rt) 82 { 83 sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); 84 } 85 86 void pushdown(int rt,int m) 87 { 88 if(add[rt]) 89 { 90 add[rt<<1]+=add[rt]; 91 add[rt<<1|1]+=add[rt]; 92 sum[rt<<1]+=add[rt]*(m-(m>>1)); 93 sum[rt<<1|1]+=add[rt]*(m>>1); 94 add[rt]=0; 95 } 96 } 97 98 void build(int l,int r,int rt) 99 { 100 add[rt]=0; 101 if(l==r) 102 { 103 sum[rt]=w[order[l]]; 104 return ; 105 } 106 int m=(l+r)>>1; 107 build(lson); 108 build(rson); 109 pushup(rt); 110 } 111 void update(int L,int R,int c,int l,int r,int rt) 112 { 113 if(L<=l&&r<=R) 114 { 115 add[rt]+=c; 116 sum[rt]+=c*(r-l+1); 117 return ; 118 } 119 pushdown(rt,r-l+1); 120 int m=(l+r)>>1; 121 if(L<=m) update(L,R,c,lson); 122 if(R>m) update(L,R,c,rson); 123 pushup(rt); 124 } 125 int query(int pos,int l,int r,int rt) 126 { 127 if(l==r) return sum[rt]; 128 pushdown(rt,r-l+1); 129 int m=(l+r)>>1; 130 int ans=0; 131 if(pos<=m) ans=query(pos,lson); 132 else ans=query(pos,rson); 133 pushup(rt); 134 return ans; 135 } 136 137 void change(int x,int y,int c) 138 { 139 while(top[x]!=top[y]) //不在一条链 140 { 141 if(dep[top[x]]<dep[top[y]]) swap(x,y); 142 update(tid[top[x]],tid[x],c,1,n,1); // 更新链首深度大的那一条链 143 x=f[top[x]]; // x所在链已更新完,将x记为x与y连接的那个点 144 } 145 if(dep[x]>dep[y]) swap(x,y); 146 update(tid[x],tid[y],c,1,n,1); 147 } 148 149 int main() 150 { 151 char op[3]; 152 int a,b,c; 153 int u,v; 154 while(scanf("%d%d%d",&n,&m,&q)!=EOF) 155 { 156 init(); 157 for(int i=1;i<=n;i++) 158 scanf("%d",&w[i]); 159 for(int i=1;i<=m;i++) 160 { 161 scanf("%d%d",&u,&v); 162 adde(u,v); 163 adde(v,u); 164 } 165 dfs1(1,0,0); 166 dfs2(1,1); 167 build(1,n,1); 168 while(q--) 169 { 170 scanf("%s",op); 171 if(op[0]=='Q') 172 { 173 scanf("%d",&a); 174 printf("%d\n",query(tid[a],1,n,1)); 175 } 176 else 177 { 178 scanf("%d%d%d",&a,&b,&c); 179 if(op[0]=='D') c=-c; 180 change(a,b,c); 181 } 182 } 183 } 184 return 0; 185 }