zoukankan      html  css  js  c++  java
  • UESTC 574 High-level ancients

    分析:

    无论父节点增加了多少,子节点的增量总比父节点多1。

    这种差分的关系是保存不变的,我们可以一遍dfs根据结点深度得到在根结点的每个点的系数。

    估且把一开始的结点深度称做c0吧,对于子树的修改就只是结点的系数就只是c0+d,d是修正值。

    dfs得到树的dfs序列,子树的结点连续,就变成区间更新了。

    区间更新的时候,在线段树上保存好初始的系数,修改的时候把系数的lazy标记和普通的lazy标记分开。

    这道题学到的新东西:在线段树上不仅可以总体+d,还可以总体增加某一系列特定的系数

    这个系数甚至是可变的,感觉这里可以挖掘一下。

    /*********************************************************
    *            ------------------                          *
    *   author AbyssFish                                     *
    **********************************************************/
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<numeric>
    #include<climits>
    using namespace std;
    
    typedef long long ll;
    const int MAX_N = 5e4+5;
    //MAX_P = 1e5 , K <= 1e3
    int fa[MAX_N];
    int son[MAX_N], bro[MAX_N];
    
    int N;
    int dep[MAX_N];
    
    int L[MAX_N], R[MAX_N];
    int c[MAX_N]; //dfs_order
    int dfs_clk;
    
    void dfs(int u = 1,int d = 1)
    {
        c[dfs_clk] = dep[u] = d;
        L[u] = dfs_clk++;
        for(int v = son[u]; v; v = bro[v]){
            dfs(v,d+1);
        }
        R[u] = dfs_clk;
    }
    
    
    #define para int o = 1,int l = 0,int r = N
    #define lo (o<<1)
    #define ro (o<<1|1)
    #define Tvar int md = (l+r)>>1;
    #define lsn lo,l,md
    #define rsn ro,md,r
    #define insd ql <= l && r <= qr
    
    const int ST_SIZE = 1<<17;
    ll t_c[ST_SIZE];//O 5e4*5e4/2
    ll sum[ST_SIZE];//O 1e5*(1e3*5e4+5e4*5e4/2)
    int dwn_c[ST_SIZE];//O 1e5
    ll dwn[ST_SIZE];//O (5e4+1e3)*1e5
    
    void build(para)
    {
        sum[o] = 0;
        if(r-l == 1){
            t_c[o] = c[l];
        }
        else {
            dwn_c[o] = dwn[o] = 0;
            Tvar
            build(lsn);
            build(rsn);
            t_c[o] = t_c[lo]+t_c[ro];
        }
    }
    
    
    inline void sink_d(int o,ll d,int len)
    {
        sum[o] += len*d;
        dwn[o] += d;
    }
    
    inline void sink_c(int o,int k)
    {
        sum[o] += t_c[o]*k;
        dwn_c[o] += k;
    }
    
    inline void push_down(int o,int l,int r)
    {
        if(dwn_c[o]){
            sink_c(lo,dwn_c[o]);
            sink_c(ro,dwn_c[o]);
            dwn_c[o] = 0;
        }
        if(dwn[o]){
            Tvar
            sink_d(lo,dwn[o],md-l);
            sink_d(ro,dwn[o],r-md);
            dwn[o] = 0;
        }
    }
    
    #define upara d,ql,qr
    void update(int d,int ql,int qr,para)
    {
        if(insd){
            sink_d(o,d,r-l);//O 5e4+1e3
            sink_c(o,1);
        }
        else {
            Tvar
            push_down(o,l,r);
            if(ql < md) update(upara,lsn);
            if(qr > md) update(upara,rsn);
            sum[o] = sum[lo] + sum[ro];
        }
    }
    
    ll query(int ql,int qr,para)
    {
        if(insd) return sum[o];
        else {
            Tvar
            push_down(o,l,r);
            ll re = 0;
            if(ql < md) re += query(ql,qr,lsn);
            if(qr > md) re += query(ql,qr,rsn);
            return re;
        }
    }
    
    void solve()
    {
        int i, P;
        scanf("%d%d",&N,&P);
        memset(son+1,0,sizeof(int)*N);
        for(i = 2; i <= N; i++){
            scanf("%d",fa+i);
            bro[i] = son[fa[i]];
            son[fa[i]] = i;
        }
    
        dfs_clk = 0;
        dfs();
        build();
    
        char op[2];
        int u;
        while(P--){
            scanf("%s%d",op,&u);
            if(*op == 'A'){
                scanf("%d",&i);
                update(i-dep[u],L[u],R[u]);
            }
            else {
                printf("%lld
    ",query(L[u],R[u]));
            }
        }
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        int T, kas = 0;
        scanf("%d",&T);
        while(++kas <= T){
            printf("Case #%d:
    ",kas);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    TestNG DataProvider的几种方法写法
    ruby操作EXCEL的简单示例
    QTP的tsr对象库文件转换成XML
    Ruby对时间的处理
    java读取YAML文件
    ruby遍历文件夹
    ruby操作excel文件
    [转载]利用ruby的Net::HTTP发起http请求并对返回包进行简单的校验
    QTP连接MySQL (转载)
    Ruby 冒泡排序
  • 原文地址:https://www.cnblogs.com/jerryRey/p/5043926.html
Copyright © 2011-2022 走看看