BOJ 331 树形DP

来源:互联网 发布:删除搜狗输入法云计算 编辑:程序博客网 时间:2024/05/22 22:53

这题是一个很明显的树形DP,不过修改和查询有1W次。

先从不是叶子结点的位置DP一次,得到一个结果。然后每次修改某个结点的值得时候,只需要修改跟其有关的路径即可。

/*ID: sdj22251PROG: inflateLANG: C++*/#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 151111#define INF 1000000000#define L(x) x<<1#define R(x) x<<1|1#define PI acos(-1.0)#define eps 1e-7#define MIN(a, b) ((a) < (b) ? (a) : (b))using namespace std;int a[MAXN];int dp[MAXN];int n, h, ans;int er[20] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072};int main(){    int x, y, z;    while(scanf("%d", &h) != EOF)    {        n = er[h] - 1;        for(int i = 1; i <= n; i++)        scanf("%d", &a[i]);        int m;        int t = er[h - 1] - 1;        for(int i = n; i > t; i--)            dp[i] = a[i];        for(int i = t; i >= 1; i--)            dp[i] = MIN(dp[2 * i], dp[2 * i + 1]) + a[i];        printf("%d\n", dp[1]);        scanf("%d", &m);        while(m--)        {            scanf("%d%d%d", &x, &y, &z);            t = er[x - 1] - 1+ y;            a[t] = z;            while(t)            {                dp[t] = MIN(dp[2 * t], dp[2 * t + 1]) + a[t];                t /= 2;            }            printf("%d\n", dp[1]);        }    }    return 0;}


原创粉丝点击