洛谷P4719 动态dp
动态DP其实挺简单一个东西。
把DP值的定义改成去掉重儿子之后的DP值。
重链上的答案就用线段树/lct维护,维护子段/矩阵都可以。其实本质上差不多...
修改的时候在log个线段树上修改。轻儿子所在重链的线段树的根拿去更新父亲的DP值。
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 100010, INF = 0x3f3f3f3f; 5 6 template <class T> inline void read(T &x) { 7 x = 0; 8 char c = getchar(); 9 bool f = 0; 10 while(c < '0' || c > '9') { 11 if(c == '-') { 12 f = 1; 13 } 14 c = getchar(); 15 } 16 while(c >= '0' && c <= '9') { 17 x = (x << 3) + (x << 1) + c - 48; 18 c = getchar(); 19 } 20 if(f) { 21 x = (~x) + 1; 22 } 23 return; 24 } 25 26 struct Edge { 27 int nex, v; 28 }edge[N << 1]; int tp; 29 30 // 0 0 0 31 // 1 0 1 32 // 2 1 0 33 // 3 1 1 34 35 int top[N], e[N], siz[N], pos[N], id[N], val[N], fa[N], son[N], d[N], num, n, len[N]; 36 int f[N][2], seg[N * 4][4], tot, ls[N * 4], rs[N * 4], rt[N]; 37 38 inline void add(int x, int y) { 39 tp++; 40 edge[tp].v = y; 41 edge[tp].nex = e[x]; 42 e[x] = tp; 43 return; 44 } 45 46 void DFS_1(int x, int f) { // son siz fa d 47 fa[x] = f; 48 d[x] = d[f] + 1; 49 siz[x] = 1; 50 for(int i = e[x]; i; i = edge[i].nex) { 51 int y = edge[i].v; 52 if(y == f) { 53 continue; 54 } 55 DFS_1(y, x); 56 siz[x] += siz[y]; 57 if(siz[y] > siz[son[x]]) { 58 son[x] = y; 59 } 60 } 61 return; 62 } 63 64 void DFS_2(int x, int f) { // pos id top 65 top[x] = f; 66 pos[x] = ++num; 67 id[num] = x; 68 len[x] = 1; 69 if(son[x]) { 70 DFS_2(son[x], f); 71 len[x] = len[son[x]] + 1; 72 } 73 for(int i = e[x]; i; i = edge[i].nex) { 74 int y = edge[i].v; 75 if(y == son[x] || y == fa[x]) { 76 continue; 77 } 78 DFS_2(y, y); 79 } 80 return; 81 } 82 83 inline void pushup(int o) { 84 int l = ls[o], r = rs[o]; 85 seg[o][0] = std::max(seg[l][0] + seg[r][0], seg[l][0] + seg[r][2]); 86 seg[o][0] = std::max(seg[o][0], seg[l][1] + seg[r][0]); 87 88 seg[o][1] = std::max(seg[l][0] + seg[r][1], seg[l][0] + seg[r][3]); 89 seg[o][1] = std::max(seg[o][1], seg[l][1] + seg[r][1]); 90 91 seg[o][2] = std::max(seg[l][2] + seg[r][0], seg[l][2] + seg[r][2]); 92 seg[o][2] = std::max(seg[o][2], seg[l][3] + seg[r][0]); 93 94 seg[o][3] = std::max(seg[l][2] + seg[r][1], seg[l][2] + seg[r][3]); 95 seg[o][3] = std::max(seg[o][3], seg[l][3] + seg[r][1]); 96 return; 97 } 98 99 inline void build(int l, int r, int &o) { 100 if(!o) { 101 o = ++tot; 102 } 103 if(l == r) { 104 seg[o][0] = f[id[r]][0]; 105 seg[o][1] = -INF; 106 seg[o][2] = -INF; 107 seg[o][3] = val[id[r]] + f[id[r]][1]; 108 return; 109 } 110 int mid = (l + r) >> 1; 111 build(l, mid, ls[o]); 112 build(mid + 1, r, rs[o]); 113 pushup(o); 114 return; 115 } 116 117 void change(int p, int l, int r, int o) { 118 //printf("change -- : %d %d %d \n", p, l, r); 119 if(l == r) { 120 seg[o][0] = f[id[r]][0]; 121 seg[o][1] = -INF; 122 seg[o][2] = -INF; 123 seg[o][3] = val[id[r]] + f[id[r]][1]; 124 //printf("%d = %d + %d \n", id[r], val[id[r]], f[id[r]][1]); 125 return; 126 } 127 int mid = (l + r) >> 1; 128 if(p <= mid) { 129 change(p, l, mid, ls[o]); 130 } 131 else { 132 change(p, mid + 1, r, rs[o]); 133 } 134 pushup(o); 135 //printf("%d %d \n", id[l], id[r]); 136 //printf("%d %d %d %d \n", seg[o][0], seg[o][1], seg[o][2], seg[o][3]); 137 return; 138 } 139 140 inline void change(int x, int v) { 141 //printf("change %d %d \n", x, v); 142 val[x] = v; 143 while(x) { 144 int xx = top[x]; 145 if(fa[xx]) { 146 int temp = std::max(seg[rt[xx]][0], seg[rt[xx]][1]); 147 f[fa[xx]][1] -= temp; 148 f[fa[xx]][0] -= std::max(std::max(seg[rt[xx]][2], seg[rt[xx]][3]), temp); 149 } 150 //printf("ch %d %d %d \n", x, xx, id[pos[xx] + len[xx] - 1]); 151 change(pos[x], pos[xx], pos[xx] + len[xx] - 1, rt[xx]); 152 if(fa[xx]) { 153 int temp = std::max(seg[rt[xx]][0], seg[rt[xx]][1]); 154 f[fa[xx]][1] += temp; 155 f[fa[xx]][0] += std::max(std::max(seg[rt[xx]][2], seg[rt[xx]][3]), temp); 156 } 157 x = fa[xx]; 158 } 159 return; 160 } 161 162 int main() { 163 int m; 164 read(n); read(m); 165 for(int i = 1; i <= n; i++) { 166 read(val[i]); 167 } 168 for(int i = 1, x, y; i < n; i++) { 169 read(x); read(y); 170 add(x, y); 171 add(y, x); 172 } 173 DFS_1(1, 0); 174 DFS_2(1, 1); 175 for(int i = 1; i <= n; i++) { 176 int x = id[n + 1 - i]; 177 if(top[x] == x) { 178 build(pos[x], pos[x] + len[x] - 1, rt[x]); 179 if(fa[x]) { 180 int temp = std::max(seg[rt[x]][0], seg[rt[x]][1]); 181 f[fa[x]][1] += temp; 182 f[fa[x]][0] += std::max(std::max(seg[rt[x]][2], seg[rt[x]][3]), temp); 183 } 184 } 185 } 186 187 for(int i = 1, x, y; i <= m; i++) { 188 read(x); read(y); 189 change(x, y); 190 int a = std::max(seg[rt[1]][0], seg[rt[1]][1]); 191 int b = std::max(seg[rt[1]][2], seg[rt[1]][3]); 192 printf("%d\n", std::max(a, b)); 193 } 194 195 return 0; 196 }
还有noip最后一题,虽然正解是倍增DP但是显然写动态DP啊...
注意树剖和线段树别写错了..没开O2少用std的函数
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 6 typedef long long LL; 7 const int N = 100010; 8 const LL INF = 1e17; 9 10 template <class T> inline void read(T &x) { 11 x = 0; 12 char c = getchar(); 13 while(c < '0' || c > '9') { 14 c = getchar(); 15 } 16 while(c >= '0' && c <= '9') { 17 x = (x << 3) + (x << 1) + c - 48; 18 c = getchar(); 19 } 20 return; 21 } 22 23 struct Edge { 24 int nex, v; 25 }edge[N * 2]; int tp; 26 27 LL val[N], f[N * 4][2][2], Val[N][2]; 28 int e[N], n, m; 29 int fa[N], top[N], pos[N], id[N], siz[N], son[N], num, d[N], ed[N]; // tree div 30 int tot, ls[N * 4], rs[N * 4], rt[N]; // segment tree 31 char str[3]; 32 33 inline void add(int x, int y) { 34 tp++; 35 edge[tp].v = y; 36 edge[tp].nex = e[x]; 37 e[x] = tp; 38 return; 39 } 40 41 void DFS_1(int x, int f) { // fa son siz d 42 fa[x] = f; 43 siz[x] = 1; 44 d[x] = d[f] + 1; 45 for(int i = e[x]; i; i = edge[i].nex) { 46 int y = edge[i].v; 47 if(y == f) { 48 continue; 49 } 50 DFS_1(y, x); 51 siz[x] += siz[y]; 52 if(siz[y] > siz[son[x]]) { 53 son[x] = y; 54 } 55 } 56 //printf("son %d = %d \n", x, son[x]); 57 //printf("siz %d = %d \n", x, siz[x]); 58 return; 59 } 60 61 void DFS_2(int x, int f) { // top pos id 62 pos[x] = ++num; 63 top[x] = f; 64 id[num] = x; 65 ed[f] = num; 66 //printf("x = %d ed %d = %d \n", x, f, ed[f]); 67 if(son[x]) { 68 DFS_2(son[x], f); 69 } 70 for(int i = e[x]; i; i = edge[i].nex) { 71 int y = edge[i].v; 72 if(y == fa[x] || y == son[x]) { 73 continue; 74 } 75 DFS_2(y, y); 76 } 77 return; 78 } 79 80 inline LL mymin(LL x, LL y) { 81 return x < y ? x : y; 82 } 83 84 inline void exmin(LL &a, LL b) { 85 a > b ? a = b : 0; 86 return; 87 } 88 89 inline void pushup(int o) { 90 int l = ls[o], r = rs[o]; 91 f[o][0][0] = INF; 92 exmin(f[o][0][0], f[l][0][1] + f[r][0][0]); 93 exmin(f[o][0][0], f[l][0][1] + f[r][1][0]); 94 exmin(f[o][0][0], f[l][0][0] + f[r][1][0]); 95 f[o][0][1] = INF; 96 exmin(f[o][0][1], f[l][0][1] + f[r][0][1]); 97 exmin(f[o][0][1], f[l][0][1] + f[r][1][1]); 98 exmin(f[o][0][1], f[l][0][0] + f[r][1][1]); 99 f[o][1][0] = INF; 100 exmin(f[o][1][0], f[l][1][1] + f[r][0][0]); 101 exmin(f[o][1][0], f[l][1][1] + f[r][1][0]); 102 exmin(f[o][1][0], f[l][1][0] + f[r][1][0]); 103 f[o][1][1] = INF; 104 exmin(f[o][1][1], f[l][1][1] + f[r][0][1]); 105 exmin(f[o][1][1], f[l][1][1] + f[r][1][1]); 106 exmin(f[o][1][1], f[l][1][0] + f[r][1][1]); 107 return; 108 } 109 110 void build(int l, int r, int &o) { 111 if(!o) { 112 o = ++tot; 113 } 114 if(l == r) { 115 // init 116 int x = id[r]; 117 f[o][0][0] = Val[x][0]; 118 f[o][0][1] = INF; 119 f[o][1][0] = INF; 120 f[o][1][1] = val[x] + Val[x][1]; 121 return; 122 } 123 int mid = (l + r) >> 1; 124 build(l, mid, ls[o]); 125 build(mid + 1, r, rs[o]); 126 pushup(o); 127 return; 128 } 129 130 inline int lca(int x, int y) { 131 while(top[x] != top[y]) { 132 if(d[top[x]] <= d[top[y]]) { 133 y = fa[top[y]]; 134 } 135 else { 136 x = fa[top[x]]; 137 } 138 } 139 return (d[x] < d[y]) ? x : y; 140 } 141 142 inline bool link(int x, int y) { 143 int z = lca(x, y); 144 return std::abs(d[x] - d[y]) == 1 && (z == x || z == y); 145 } 146 147 inline void change(int p, int v, int l, int r, int o) { 148 //printf("change %d %d %d %d \n", p, v, l, r); 149 if(l == r) { 150 if(v) { 151 f[o][0][0] = INF; 152 } 153 else { 154 f[o][1][1] = INF; 155 } 156 return; 157 } 158 int mid = (l + r) >> 1; 159 if(p <= mid) { 160 change(p, v, l, mid, ls[o]); 161 } 162 else { 163 change(p, v, mid + 1, r, rs[o]); 164 } 165 pushup(o); 166 return; 167 } 168 169 inline void update(int p, int l, int r, int o) { 170 if(l == r) { 171 int x = id[r]; 172 f[o][0][0] = Val[x][0]; 173 f[o][1][1] = val[x] + Val[x][1]; 174 return; 175 } 176 int mid = (l + r) >> 1; 177 if(p <= mid) { 178 update(p, l, mid, ls[o]); 179 } 180 else { 181 update(p, mid + 1, r, rs[o]); 182 } 183 pushup(o); 184 return; 185 } 186 187 inline void change(int x, int a) { 188 int xx = x; 189 while(x) { 190 if(fa[top[x]]) { 191 LL temp = mymin(f[rt[top[x]]][1][0], f[rt[top[x]]][1][1]); 192 Val[fa[top[x]]][0] -= temp; 193 Val[fa[top[x]]][1] -= mymin(mymin(f[rt[top[x]]][0][0], f[rt[top[x]]][0][1]), temp); 194 } 195 if(x != xx) 196 update(pos[x], pos[top[x]], ed[top[x]], rt[top[x]]); 197 else 198 change(pos[x], a, pos[top[x]], ed[top[x]], rt[top[x]]); 199 if(fa[top[x]]) { 200 LL temp = mymin(f[rt[top[x]]][1][0], f[rt[top[x]]][1][1]); 201 Val[fa[top[x]]][0] += temp; 202 Val[fa[top[x]]][1] += mymin(mymin(f[rt[top[x]]][0][0], f[rt[top[x]]][0][1]), temp); 203 } 204 x = fa[top[x]]; 205 } 206 return; 207 } 208 209 inline void recover(int x) { 210 while(x) { 211 if(fa[top[x]]) { 212 LL temp = mymin(f[rt[top[x]]][1][0], f[rt[top[x]]][1][1]); 213 Val[fa[top[x]]][0] -= temp; 214 Val[fa[top[x]]][1] -= mymin(mymin(f[rt[top[x]]][0][0], f[rt[top[x]]][0][1]), temp); 215 } 216 update(pos[x], pos[top[x]], ed[top[x]], rt[top[x]]); 217 if(fa[top[x]]) { 218 LL temp = mymin(f[rt[top[x]]][1][0], f[rt[top[x]]][1][1]); 219 Val[fa[top[x]]][0] += temp; 220 Val[fa[top[x]]][1] += mymin(mymin(f[rt[top[x]]][0][0], f[rt[top[x]]][0][1]), temp); 221 } 222 x = fa[top[x]]; 223 } 224 return; 225 } 226 227 int main() { 228 229 //freopen("in.in", "r", stdin); 230 //freopen("my.out", "w", stdout); 231 read(n); read(m); 232 scanf("%s", str); 233 for(register int i = 1; i <= n; i++) { 234 read(val[i]); 235 } 236 for(register int i = 1, x, y; i < n; i++) { 237 read(x); read(y); 238 add(x, y); add(y, x); 239 } 240 // prework 241 DFS_1(1, 0); 242 DFS_2(1, 1); 243 // build 244 for(register int a = n; a >= 1; a--) { 245 int x = id[a]; 246 if(top[x] == x) { 247 build(pos[x], ed[x], rt[x]); 248 if(fa[x]) { 249 int father = fa[x]; 250 LL temp = mymin(f[rt[x]][1][0], f[rt[x]][1][1]); 251 Val[father][0] += temp; 252 Val[father][1] += mymin(mymin(f[rt[x]][0][0], f[rt[x]][0][1]), temp); 253 } 254 } 255 } 256 257 for(register int i = 1, x, a, y, b; i <= m; i++) { 258 scanf("%d%d%d%d", &x, &a, &y, &b); 259 if(!a && !b && link(x, y)) { 260 puts("-1"); 261 continue; 262 } 263 change(x, a); 264 change(y, b); 265 printf("%lld\n", mymin(mymin(f[rt[1]][0][0], f[rt[1]][1][1]), mymin(f[rt[1]][0][1], f[rt[1]][1][0]))); 266 recover(x); 267 recover(y); 268 } 269 270 return 0; 271 }