洛谷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 }
AC代码

还有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 }
AC代码

 

posted @ 2019-02-16 20:56  huyufeifei  阅读(250)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜