zoukankan      html  css  js  c++  java
  • 2020智算之道复赛E 树数数

    传送门

     

    题意就懒得复述了

    直接对着欧拉序建线段树,每个节点用一个堆来维护标记。

    每次修改可能导致一部分区间被某个点覆盖,而且这个覆盖并不遵循后边的修改会覆盖前面的修改这样的规则,而是深度小的黑点优先于深度大的黑点,因此需要用堆来维护标记。由于区间只会完全包含,不会出现交叉的情况,可以标记永久化,删除也容易处理。

    #include<stdio.h>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define ll long long 
    #define lx (x<<1)
    #define rx ((x<<1)|1)
    using namespace std;
    
    char ibuf[20000004],*iptr=ibuf-1,C;
    inline int _(){
        int x=0,c=*++iptr;
        while(c<48)c=*++iptr;
        while(c>47)x=x*10+c-48,c=*++iptr;
        return x;
    }
    inline int _char(){
        int x=0,c=*++iptr;
        while(c<'A')c=*++iptr;
        while(c>'A' && c<'Z')x=c,c=*++iptr;
        return x;
    }
    char obuf[5000000],*optr=obuf;
    inline void _(ll x){
        static int stk[32],stp=0;
        if(!x)stk[stp++]=0;
        while(x)stk[stp++]=x%10,x/=10;
        while(stp)*(optr++)=stk[--stp]+48;
        *(optr++)=10;
    }
    const int MN = 210000;
    struct na{int y,ne;}b[MN];
    int n, m, num=0, f[MN], w[MN], l[MN], si[MN], L[MN], R[MN], pdf[MN], order = 0, color[MN], deep[MN];
    ll lose[MN<<2];
    ll ans[MN<<2];
    ll co[MN];
    priority_queue<int> tag[MN<<2];
    pair<ll, ll> pair_add(pair<ll, ll> a, pair<ll, ll> b){
        return make_pair(a.first+b.first, a.second+b.second);
    }
    inline void in(int x,int y){b[++num].y=y;b[num].ne=l[x];l[x]=num;}
    void dfs1(int x){
        si[x] = 1;
        L[x] = ++order;
        pdf[order] = x;
        for (int i = l[x]; i; i = b[i].ne){
            dfs1(b[i].y);
            co[x] += 1ll*si[x]*si[b[i].y];
            si[x] += si[b[i].y];
        }
        R[x] = order;
    }
    void build(int x, int l, int r){
        if (l == r){
            lose[x] = co[pdf[l]];
            return;
        }
        int mid = l+r>>1;
        build(lx, l ,mid);
        build(rx, mid+1, r);
        lose[x] = lose[lx]+lose[rx];
    }
    void update(int x, int l, int r){
        if (l == r){
            ans[x] = 0;
            lose[x] = co[pdf[l]];
        }else{
            ans[x] = ans[lx] + ans[rx];
            lose[x] = lose[lx] + lose[rx];
        }
        
        while(tag[x].size() && (!color[tag[x].top()])) tag[x].pop();
        if (tag[x].size()){
            ans[x] += lose[x] * w[tag[x].top()];
            lose[x] = 0;
        }
    }
    pair<ll, ll> ask(int x, int l, int r, int L, int R){
        if (l == L && r == R){
            return make_pair(ans[x], lose[x]);
        }
        int mid = l+r>>1;
        pair<ll, ll> res;
        if (R <= mid){
            res = ask(lx, l, mid, L, R);
        }else if (L > mid){
            res = ask(rx, mid+1, r, L, R);
        }else{
            res = pair_add(ask(lx, l, mid, L, mid), ask(rx, mid+1, r, mid+1, R));
        }
        while(tag[x].size() && (!color[tag[x].top()])) tag[x].pop();
        if (tag[x].size()){
            res.first += res.second * w[tag[x].top()];
            res.second = 0;
        }
        return res;
    }
    void addTag(int x, int l, int r, int L, int R, int p){
        if (l == L && r == R){
            if (color[p]){
                tag[x].push(p);
            }
            update(x, l, r);
            return;
        }
        int mid = l + r >> 1;
        if (R <= mid){
            addTag(lx, l, mid, L, R, p);
        }else if (L > mid){
            addTag(rx, mid+1, r, L, R, p);
        }else{
            addTag(lx, l, mid, L, mid, p);
            addTag(rx, mid+1, r, mid+1, R, p);
        }
        update(x, l, r);
    }
    int main(){
        ibuf[fread(ibuf,1,20000000,stdin)]=0;
        n = _();
        m = _();
        for (int i = 2; i <= n; i++) f[i] = _(), in(f[i], i);
        for (int i = 1; i <= n; i++) w[i] = _();
        dfs1(1);
        build(1, 1, n);
        while (m--){
            char s = _char();
            if (s == 'Q'){
                int x = _();
                _(ask(1, 1, n, L[x], R[x]).first);
            }else if (s == 'F'){
                int x = _();
                color[x]^=1;
                addTag(1, 1, n, L[x], R[x], x);
            }else if (s == 'M'){
                int x = _();
                w[x] = _();
                if (color[x]){
                    addTag(1, 1, n, L[x], R[x], 0);
                }
            }
        }
        fwrite(obuf,1,optr-obuf,stdout);
    }
    View Code
  • 相关阅读:
    【POJ 2987 Firing】 最大权闭合子图
    【sgu176】有源汇有上下界的最大/最小流
    【HDU1263 水果】 STL之map应用经典好题
    【HDU1227 Fast Food】经典DP
    【hdu1043 && poj 1077】八数码问题
    有上下界的网络流问题
    【HDU4521】 dp思想+线段树操作
    miracl库下椭圆曲线方程常用函数使用入门
    函数指针
    python数据查询操作之 一场缺少db.commit()引发的血案……
  • 原文地址:https://www.cnblogs.com/Enceladus/p/13463925.html
Copyright © 2011-2022 走看看