zoukankan      html  css  js  c++  java
  • luogu P3787 冰精冻西瓜

    嘟嘟嘟

    好题,好题……

    看这个修改和询问,就知道要么是求完dfs序后线段树维护,要么是树剖。又因为这道题都是子树的操作,没有链上的,所以线段树就够了。

    然而重点不是这个。这道题最麻烦的是线段树pushdown时对于每一个节点打的标记都不一样,因为每一条边上的能力值不一样。这也是这道题最巧妙的一点:我们把每一次对节点 i 放的冷气都转移到从根节点放的,这样pushdown的标记就统一了。

    具体操作是啥咧:假如u到跟要经过w1, w2, w3这三条边,那么我们对u放x的冷气,就相当于从根节点放Div[u] = w1 * w2 * w3  * x的冷气,查询v的冷气值的时候把线段树得到的答案除以Div[v]即可。预处理Div[i]dfs一遍即可。

    然而这道题还没完,因为Div[i]可以等于0,所以这棵树实际上会断成一个森林。所以就有好多个根节点,以及好多棵线段树,但是空间大小是不变的。

    所以要记录每一棵树的根节点,再从根节点开始dfs,维护的Div[i]实际上表示的是 i 到他所在的树的根节点的Πwi。(一定是从根节点开始!我就是因为从树中任意一棵节点开始导致85分,今天听bin哥讲完后突然才想出来这个问题)

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-9;
     20 const int maxn = 1e5 + 5;
     21 inline ll read()
     22 {
     23   ll ans = 0;
     24   char ch = getchar(), last = ' ';
     25   while(!isdigit(ch)) {last = ch; ch = getchar();}
     26   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27   if(last == '-') ans = -ans;
     28   return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32   if(x < 0) x = -x, putchar('-');
     33   if(x >= 10) write(x / 10);
     34   putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m;
     38 struct Edge
     39 {
     40   int nxt, to;
     41   db w;
     42 }e[maxn << 1];
     43 int head[maxn], ecnt = -1;
     44 void addEdge(int x, int y, db w)
     45 {
     46   e[++ecnt] = (Edge){head[x], y, w};
     47   head[x] = ecnt;
     48 }
     49 
     50 int st[maxn], top = 0;
     51 bool vis[maxn];
     52 int rt[maxn], bel[maxn];
     53 int siz[maxn], dfsx[maxn], pos[maxn], cnt = 0;
     54 db Div[maxn];
     55 bool zero(db x)
     56 {
     57   return x >= -eps && x <= eps;
     58 }
     59 void dfs(int now, int id)
     60 {
     61   vis[now] = 1; siz[now] = 1; bel[now] = id;
     62   dfsx[now] = ++cnt; pos[cnt] = now;
     63   for(int i = head[now]; i != -1; i = e[i].nxt)
     64     {
     65       if(vis[e[i].to]) continue;
     66       if(zero(e[i].w)) st[++top] = e[i].to;
     67       else
     68     {
     69       Div[e[i].to] = Div[now] * e[i].w;
     70       dfs(e[i].to, id);
     71       siz[now] += siz[e[i].to];
     72     }
     73     }
     74 }
     75 
     76 int ls[maxn << 2], rs[maxn << 2], ctr = 0;
     77 db sum[maxn << 2], lzy[maxn << 2];
     78 void pushdown(int now)
     79 {
     80   if(!zero(lzy[now]))
     81     {
     82       if(!ls[now]) ls[now] = ++ctr;
     83       if(!rs[now]) rs[now] = ++ctr;
     84       sum[ls[now]] += lzy[now]; sum[rs[now]] += lzy[now];
     85       lzy[ls[now]] += lzy[now]; lzy[rs[now]] += lzy[now];
     86       lzy[now] = 0;
     87     }
     88 }
     89 void update(int l, int r, int L, int R, int& now, db d)
     90 {
     91   if(!now) now = ++ctr;
     92   if(l == L && r == R) {sum[now] += d; lzy[now] += d; return;}
     93   pushdown(now);
     94   int mid = (l + r) >> 1;
     95   if(R <= mid) update(l, mid, L, R, ls[now], d);
     96   else if(L > mid) update(mid + 1, r, L, R, rs[now], d);
     97   else update(l, mid, L, mid, ls[now], d), update(mid + 1, r, mid + 1, R, rs[now], d);
     98 }
     99 db query(int l, int r, int& now, int id)
    100 {
    101   if(!now) now = ++ctr;
    102   if(l == r) return sum[now] * Div[pos[id]];
    103   pushdown(now);
    104   int mid = (l + r) >> 1;
    105   if(id <= mid) return query(l, mid, ls[now], id);
    106   else return query(mid + 1, r, rs[now], id);
    107 }
    108 
    109 int main()
    110 {
    111   Mem(head, -1);
    112   n = read();
    113   for(int i = 1; i < n; ++i)
    114     {
    115       int x = read(), y = read();
    116       db w; scanf("%lf", &w);
    117       addEdge(x, y, w); addEdge(y, x, w);
    118     }
    119   Div[1] = 1.00; dfs(1, 1);
    120   for(int i = 1; i <= top; ++i) Div[st[i]] = 1.00, dfs(st[i], st[i]);
    121   m = read();
    122   for(int i = 1; i <= m; ++i)
    123     {
    124       int d = read();
    125       if(d == 1)
    126     {
    127       int x = read();
    128       db w; scanf("%lf", &w);
    129       update(dfsx[bel[x]], dfsx[bel[x]] + siz[bel[x]] - 1, dfsx[x], dfsx[x] + siz[x] - 1, rt[bel[x]], w / Div[x]);
    130     }
    131       else
    132     {
    133       int x = read();
    134       printf("%.8lf
    ", query(dfsx[bel[x]], dfsx[bel[x]] + siz[bel[x]] - 1, rt[bel[x]], dfsx[x]));
    135     }
    136     }
    137   return 0;
    138 }
    View Code
  • 相关阅读:
    hdu 2295 DLX
    hdu 4714 树形DP
    hdu 4711 动态规划
    hdu 3656 DLX
    hust 1017 DLX
    hdu 3938 并查集
    hdu 3652 打表
    poj 2152 树形DP
    洛谷P1266速度限制
    洛谷P1841重要的城市
  • 原文地址:https://www.cnblogs.com/mrclr/p/9845892.html
Copyright © 2011-2022 走看看