月下“毛景树”(边权树链剖分)
月下“毛景树”
https://www.luogu.org/problemnew/show/P4315
题目描述
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。
爬啊爬~爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:
-
Change k w:将第k条树枝上毛毛果的个数改变为w个。
-
Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
-
Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:
-
Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
输入输出格式
输入格式:
第一行一个正整数N。
接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。
输出格式:
对于毛毛虫的每个询问操作,输出一个答案。
输入输出样例
说明
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
裸的树链剖分,要注意的点就是覆盖的优先级比加法的大,重点就是pushdown函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<cstdio> 6 #include<algorithm> 7 #include<vector> 8 #define maxn 100005 9 #define lson l,mid,rt<<1 10 #define rson mid+1,r,rt<<1|1 11 using namespace std; 12 13 int tree[maxn<<3],Add[maxn<<3],Change[maxn<<3]; 14 int n; 15 int v[maxn],val[maxn]; 16 int dep[maxn],fa[maxn],siz[maxn],son[maxn],id[maxn],top[maxn],cnt; 17 vector<int>ve[maxn]; 18 struct sair{ 19 int x,y,len; 20 }p[maxn]; 21 22 void pushup(int rt){ 23 tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); 24 } 25 26 void pushdown(int rt){ 27 if(Change[rt]!=-1){ 28 Change[rt<<1]=Change[rt<<1|1]=Change[rt]; 29 Add[rt<<1]=Add[rt<<1|1]=0; 30 tree[rt<<1]=tree[rt<<1|1]=Change[rt]; 31 } 32 if(Add[rt]){ 33 Add[rt<<1]+=Add[rt]; 34 Add[rt<<1|1]+=Add[rt]; 35 tree[rt<<1]+=Add[rt]; 36 tree[rt<<1|1]+=Add[rt]; 37 } 38 Change[rt]=-1; 39 Add[rt]=0; 40 } 41 42 void build(int l,int r,int rt){ 43 Add[rt]=0; 44 Change[rt]=-1; 45 if(l==r){ 46 tree[rt]=val[l]; 47 return; 48 } 49 int mid=(l+r)/2; 50 build(lson); 51 build(rson); 52 pushup(rt); 53 } 54 55 void add(int L,int R,int k,int l,int r,int rt){ 56 if(L<=l&&R>=r){ 57 tree[rt]+=k; 58 Add[rt]+=k; 59 pushdown(rt); 60 return; 61 } 62 int mid=(l+r)/2; 63 pushdown(rt); 64 if(L<=mid) add(L,R,k,lson); 65 if(R>mid) add(L,R,k,rson); 66 pushup(rt); 67 } 68 69 void change(int L,int R,int k,int l,int r,int rt){ 70 if(L<=l&&R>=r){ 71 tree[rt]=k; 72 Add[rt]=0; 73 Change[rt]=k; 74 pushdown(rt); 75 return; 76 } 77 int mid=(l+r)/2; 78 pushdown(rt); 79 if(L<=mid) change(L,R,k,lson); 80 if(R>mid) change(L,R,k,rson); 81 pushup(rt); 82 } 83 84 int query(int L,int R,int l,int r,int rt){ 85 if(L<=l&&R>=r){ 86 return tree[rt]; 87 } 88 int mid=(l+r)/2; 89 pushdown(rt); 90 int ans=0; 91 if(L<=mid) ans=max(ans,query(L,R,lson)); 92 if(R>mid) ans=max(ans,query(L,R,rson)); 93 pushup(rt); 94 return ans; 95 } 96 97 void dfs1(int now,int f,int deep){ 98 dep[now]=deep; 99 siz[now]=1; 100 fa[now]=f; 101 int maxson=-1; 102 for(int i=0;i<ve[now].size();i++){ 103 if(ve[now][i]==f) continue; 104 dfs1(ve[now][i],now,deep+1); 105 siz[now]+=siz[ve[now][i]]; 106 if(siz[ve[now][i]]>maxson){ 107 maxson=siz[ve[now][i]]; 108 son[now]=ve[now][i]; 109 } 110 } 111 } 112 113 void dfs2(int now,int topp){ 114 id[now]=++cnt; 115 val[cnt]=v[now]; 116 top[now]=topp; 117 if(!son[now]) return; 118 dfs2(son[now],topp); 119 for(int i=0;i<ve[now].size();i++){ 120 if(ve[now][i]==son[now]||ve[now][i]==fa[now]) continue; 121 dfs2(ve[now][i],ve[now][i]); 122 } 123 } 124 125 int qRange(int x,int y){ 126 int t1 = top[x], t2 = top[y]; 127 int res = 0; 128 while(t1 != t2) { 129 if(dep[t1] < dep[t2]) { 130 swap(t1, t2); swap(x, y); 131 } 132 res = max(res,query(id[t1], id[x], 1, n, 1)); 133 x = fa[t1]; t1 = top[x]; 134 } 135 if(x == y) return res; 136 if(dep[x] > dep[y]) swap(x, y); 137 return max(res,query(id[son[x]], id[y], 1, n, 1)); 138 } 139 140 void addRange(int x,int y,int k){ 141 int t1 = top[x], t2 = top[y]; 142 while(t1 != t2) { 143 if(dep[t1] < dep[t2]) { 144 swap(t1, t2); swap(x, y); 145 } 146 add(id[t1], id[x], k, 1, n, 1); 147 x = fa[t1]; t1 = top[x]; 148 } 149 if(x == y) return ; 150 if(dep[x] > dep[y]) swap(x, y); 151 add(id[son[x]], id[y], k, 1, n, 1); 152 } 153 154 void changeRange(int x,int y,int k){ 155 int t1 = top[x], t2 = top[y]; 156 while(t1 != t2) { 157 if(dep[t1] < dep[t2]) { 158 swap(t1, t2); swap(x, y); 159 } 160 change(id[t1], id[x], k, 1, n, 1); 161 x = fa[t1]; t1 = top[x]; 162 } 163 if(x == y) return ; 164 if(dep[x] > dep[y]) swap(x, y); 165 change(id[son[x]], id[y], k, 1, n, 1); 166 } 167 168 int main(){ 169 std::ios::sync_with_stdio(false); 170 int m,r; 171 cin>>n; 172 for(int i=1;i<n;i++){ 173 cin>>p[i].x>>p[i].y>>p[i].len; 174 ve[p[i].x].push_back(p[i].y); 175 ve[p[i].y].push_back(p[i].x); 176 } 177 int z,x,y; 178 string pos; 179 cnt=0; 180 dfs1(1,0,1); 181 dfs2(1,1); 182 build(1,n,1); 183 int xx; 184 for(int i=1;i<n;i++){ 185 if(dep[p[i].x]<dep[p[i].y]) xx=p[i].y; 186 else xx=p[i].x; 187 change(id[xx],id[xx],p[i].len,1,n,1); 188 } 189 while(cin>>pos){ 190 if(pos=="Stop") break; 191 cin>>x>>y; 192 if(pos=="Max"){ 193 cout<<qRange(x,y)<<endl; 194 } 195 else if(pos=="Cover"){ 196 cin>>z; 197 changeRange(x,y,z); 198 } 199 else if(pos=="Add"){ 200 cin>>z; 201 addRange(x,y,z); 202 } 203 else if(pos=="Change"){ 204 if(dep[p[x].x]<dep[p[x].y]) xx=p[x].y; 205 else xx=p[x].x; 206 change(id[xx],id[xx],y,1,n,1); 207 p[x].len=y; 208 } 209 } 210 } 211 /* 212 7 213 1 2 1 214 1 3 2 215 2 4 3 216 2 5 4 217 3 7 6 218 5 6 5 219 Max 1 6 220 */
posted on 2018-09-24 00:18 Fighting_sh 阅读(282) 评论(0) 编辑 收藏 举报