标签:hdu pen play for 更新 double href gcd open
参考博客:https://www.cnblogs.com/George1994/p/7821357.html
模板题:HDU 3966 Aragorn‘s Story
给一棵树每个点有权值,三种操作,一是给两个点和一个值U, V,K,U~V这条路径上所有点+K,二是U~K这条路径上所有点权值-K,三是查询某点U的权值为多少。先写着树链剖分
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <vector> 5 #include <queue> 6 #include <math.h> 7 #include <string> 8 #include <algorithm> 9 #include <time.h> 10 11 #define SIGMA_SIZE 26 12 #define lson rt<<1 13 #define rson rt<<1|1 14 #define lowbit(x) (x&-x) 15 #define foe(i, a, b) for(int i=a; i<=b; i++) 16 #define fo(i, a, b) for(int i = a; i < b; i++); 17 #pragma warning ( disable : 4996 ) 18 #pragma comment(linker, "/STACK:1024000000,1024000000") 19 20 using namespace std; 21 typedef long long LL; 22 inline LL LMax(LL a,LL b) { return a>b?a:b; } 23 inline LL LMin(LL a,LL b) { return a>b?b:a; } 24 inline LL lgcd( LL a, LL b ) { return b==0?a:lgcd(b,a%b); } 25 inline LL llcm( LL a, LL b ) { return a/lgcd(a,b)*b; } //a*b = gcd*lcm 26 inline int Max(int a,int b) { return a>b?a:b; } 27 inline int Min(int a,int b) { return a>b?b:a; } 28 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 29 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 30 const LL INF = 0x3f3f3f3f3f3f3f3f; 31 const LL mod = 1000000007; 32 const double eps = 1e-8; 33 const int inf = 0x3f3f3f3f; 34 const int maxk = 1e6+5; 35 const int maxn = 5e4+5; 36 37 int N, M, Q, tim; 38 int cnt; 39 int linjie[maxn]; 40 int sum[maxn<<2], lazy[maxn<<2]; 41 int siz[maxn]; //以i为根节点 它的子树的节点个数 42 int top[maxn]; //当前节点所在链的顶端节点编号 43 int son[maxn]; //重儿子编号 44 int faz[maxn]; //当前节点的父亲节点 45 int dep[maxn]; //深度, 46 int tid[maxn]; //树中每个节点剖分以后的新编号(dfs执行顺序) 47 int rnk[maxn]; //当前节点在树中的位置 48 struct node { 49 int to, next, val; 50 }pp[2*maxn]; 51 52 void addedge(int u, int v) 53 { pp[cnt].to = v; pp[cnt].next = linjie[u]; linjie[u] = cnt++; } 54 55 //第一次dfs更新了dep,faz,siz,son数组 56 void dfs_1(int u, int fa, int d) 57 { 58 dep[u] = d; 59 faz[u] = fa; 60 siz[u] = 1; 61 for ( int i = linjie[u]; ~i; i = pp[i].next) 62 { 63 int v = pp[i].to; 64 if ( v != faz[u] ) 65 { 66 dfs_1(v, u, d+1); 67 // 收敛的时候将当前结点的siz加上子结点的siz 68 siz[u] += siz[v]; 69 // 如果没有设置过重结点son或者子结点v的siz大于之前记录的重结点son,则进行更新 70 if (son[u] == -1 || siz[v] > siz[son[u]]) 71 son[u] = v; 72 } 73 } 74 } 75 76 void dfs_2(int u, int tp) 77 { 78 top[u] = tp; // 设置当前结点的起点为tP 79 tid[u] = ++tim; // 设置当前结点的dfs执行序号 80 rnk[tid[u]] = u; // 设置dfs序号对应成当前结点 81 82 // 如果当前结点没有处在重链上,则不处理 83 if (son[u] == -1) return; 84 // 将这条重链上的所有的结点都设置成起始的重结点 85 dfs_2(son[u], tp); 86 87 for ( int i = linjie[u]; ~i; i = pp[i].next ) 88 { 89 // 如果连接结点不是当前结点的重子结点并且也不是u的父亲结点, 90 // 则将其的top设置成自己,进一步递归 91 int v = pp[i].to; 92 if (v != son[u] && v != faz[u]) 93 dfs_2(v, v); 94 } 95 } 96 97 void pushUp(int rt) 98 { sum[rt] = Max(sum[lson], sum[rson]); } 99 100 void pushDown(int rt, int ln, int rn) 101 { 102 if (lazy[rt]) 103 { 104 lazy[lson] += lazy[rt]; 105 lazy[rson] += lazy[rt]; 106 107 sum[lson] += ln*lazy[rt]; 108 sum[rson] += rn*lazy[rt]; 109 110 lazy[rt] = 0; 111 } 112 } 113 114 void build(int rt, int L, int R) 115 { 116 lazy[rt] = 0; 117 if ( L == R ) 118 { 119 //L是dfs遍历顺序编号,rnk[L]是原来的点的编号 120 sum[rt] = pp[rnk[L]].val; 121 return; 122 } 123 124 int mid = (L+R)>>1; 125 build(lson, L, mid); 126 build(rson, mid+1, R); 127 pushUp(rt); 128 } 129 130 void update(int rt, int L, int R, int lhs, int rhs, int C) 131 { 132 if ( lhs <= L && rhs >= R ) 133 { 134 lazy[rt] += C; 135 sum[rt] += C*(R-L+1); 136 return; 137 } 138 139 int mid = (L+R)>>1; 140 pushDown(rt, mid-L+1, R-mid); 141 if ( lhs <= mid ) update(lson, L, mid, lhs, rhs, C); 142 if ( rhs > mid ) update(rson, mid+1, R, lhs, rhs, C); 143 pushUp(rt); 144 } 145 146 int query(int rt, int L, int R, int V) 147 { 148 if ( L == R ) 149 return sum[rt]; 150 151 int tmp = -1, mid = (L+R)>>1; 152 pushDown(rt, mid-L+1, R-mid); 153 if ( V <= mid ) tmp = query(lson, L, mid, V); 154 else tmp = query(rson, mid+1, R, V); 155 156 pushUp(rt); 157 return tmp; 158 } 159 160 void change(int x, int y, int val) 161 { 162 while (top[x] != top[y]) 163 { 164 //x作为找深度深的那一个节点 165 if (dep[top[x]] < dep[top[y]]) swap(x, y); 166 //将x作为一个区间的结尾,top[x]作为一个区间的起始 167 update(1, 1, N, tid[top[x]], tid[x], val); 168 //跳到更上层的链 169 x = faz[top[x]]; 170 } 171 172 //直到x和y是在同一条链上 173 if (dep[x] > dep[y]) swap(x, y); 174 update(1, 1, N, tid[x], tid[y], val); 175 } 176 177 void init() 178 { 179 tim = cnt = 0; 180 memset(linjie, -1, sizeof(linjie)); 181 memset(son, -1, sizeof(son)); 182 183 int x, y; 184 foe(i, 1, N) 185 scanf("%d", &pp[i].val); 186 foe(i, 1, M) 187 { 188 scanf("%d %d", &x, &y); 189 addedge(x, y); 190 addedge(y, x); 191 } 192 193 //父节点是0, 深度为0 194 dfs_1(1, 0, 0); 195 dfs_2(1, 1); 196 build(1, 1, N); 197 } 198 199 200 int main() 201 { 202 while ( ~scanf("%d %d %d", &N, &M, &Q) ) 203 { 204 init(); 205 206 char str[2]; 207 int x, y, d; 208 while (Q--) 209 { 210 scanf("%s", str); 211 if (str[0] == ‘I‘) { 212 scanf("%d %d %d", &x, &y, &d); 213 change(x, y, d); 214 } 215 else if (str[0] == ‘D‘) { 216 scanf("%d %d %d", &x, &y, &d); 217 change(x, y, -d); 218 } 219 else { 220 scanf("%d", &d); 221 printf("%d\n", query(1, 1, N, tid[d])); 222 } 223 } 224 } 225 return 0; 226 }
标签:hdu pen play for 更新 double href gcd open
原文地址:https://www.cnblogs.com/chaoswr/p/9362312.html