zoukankan      html  css  js  c++  java
  • P3258 [JLOI2014]松鼠的新家 树链剖分

    这个题就是一道树剖板子题,就是每走一步就把所有的经过点加一就行了。还有,我的树剖板子没问题!!!谁知道为什么板子T3个点!我不管了!反正这道题正常写A了。

    题干:

    题目描述
    
    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。
    
    松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。
    
    维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。
    
    因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
    输入输出格式
    输入格式:
    第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an
    接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
    输出格式:
    一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
    输入输出样例
    输入样例#1: 复制
    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5
    输出样例#1: 复制
    1
    2
    1
    2
    1
    说明
    2<= n <=300000

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 300010;
    struct node
    {
        int l,r,nxt;
    }a[2 * N];
    int n,len = 0,lst[N];
    int A[N],tree[4 * N];
    void add(int x,int y)
    {
        a[++len].l = x;
        a[len].r = y;
        a[len].nxt = lst[x];
        lst[x] = len;
    }
    int f[N],dep[N],son[N],siz[N],id[N],rk[N];
    int tp[N],cnt = 0,lazy[4 * N],vis[N];
    void dfs1(int u,int fa,int depth)
    {
        f[u] = fa;
        siz[u] = 1;
        dep[u] = depth;
        for(int k = lst[u];k;k = a[k].nxt)
        {
            int y = a[k].r;
            if(y == fa) continue;
            dfs1(y,u,depth + 1);
            siz[u] += siz[y];
            if(!son[u] || siz[son[u]] < siz[y])
            son[u] = y;
        }
    }
    void dfs2(int u,int t)
    {
        vis[u] = 1;
        tp[u] = t;
        id[u] = ++cnt;
        rk[cnt] = u;
        if(!son[u])
        return;
        dfs2(son[u],t);
        for(int k = lst[u];k;k = a[k].nxt)
        {
            int y = a[k].r;
            if(y == son[u] || y == f[u] || vis[y] == 1) continue;
            dfs2(y,y);
        }
    }
    void push_down(int o,int l,int r)
    {
        if(lazy[o] != 0)
        {
            int mid = (l + r) >> 1;
            tree[o << 1] += (mid - l + 1) * lazy[o];
            tree[o << 1 | 1] += (r - mid) * lazy[o];
            lazy[o << 1] += lazy[o];
            lazy[o << 1 | 1] += lazy[o];
            lazy[o] = 0;
        }
    }
    void update(int o,int l,int r,int x,int y)
    {
        int mid = (l + r) >> 1;
        if(l == x && r == y)
        {
            tree[o] += (r - l + 1);
            lazy[o] += 1;
            return;
        }
        push_down(o,l,r);
        if(mid >= y)
        update(o << 1,l,mid,x,y);
        else if(mid < x)
        update(o << 1 | 1,mid + 1,r,x,y);
        else
        {
            update(o << 1,l,mid,x,mid);
            update(o << 1 | 1,mid + 1,r,mid + 1,y);
        }
        tree[o] = tree[o << 1] + tree[o << 1 | 1];
    }
    void update2(int x,int y)
    {
        while(tp[x] != tp[y])
        {
            if(dep[tp[x]] < dep[tp[y]]) swap(x,y);
            update(1,1,n,id[tp[x]],id[x]);
            x = f[tp[x]];
        }
        if(id[x] > id[y]) swap(x,y);
        update(1,1,n,id[x],id[y]);
    }
    int query(int o,int l,int r,int id)
    {
        if(l == r)
        return tree[o];
        push_down(o,l,r);
        int mid = (l + r) >> 1;
        if(id <= mid)
        return query(o << 1,l,mid,id);
        else
        return query(o << 1 | 1,mid + 1,r,id);
    }
    int main()
    {
        read(n);
        duke(i,1,n)
        read(A[i]);
        duke(i,1,n - 1)
        {
            int x,y;
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        dfs1(1,0,0);
        dfs2(1,0);
        /*duke(i,1,n)
        printf("%d %d
    ",id[i],tp[i]);*/
    //    printf("QAQ
    ");
        duke(i,1,n - 1)
        update2(A[i],A[i + 1]);
        duke(i,1,n)
        {
            int p = query(1,1,n,id[i]);
            if(A[1] != i)
            p -= 1;
            printf("%d
    ",p);
        }
        return 0;
    }

    顺便附赠树剖板子:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    const int N = 200005;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    struct edge
    {
        int nxt,r;
    } e[4 * N];
    int n,m,r,cnt;
    int a[N],lst[N],p;
    int f[N],d[N],siz[N],son[N],rk[N];
    int top[N],id[N],tree[4 * N];
    int lazy[4 * N],len = 0;
    //id新编号dfs序
    void add(int x,int y)
    {
        e[++len].nxt = lst[x];
        e[len].r = y;
        lst[x] = len;
    }
    
    void dfs1(int u,int fa,int depth)
    {
        f[u] = fa;
        d[u] = depth;
        siz[u] = 1;
        for(int k = lst[u];k;k = e[k].nxt)
        {
            int y = e[k].r;
            if(y == fa)
                continue;
            dfs1(y,u,depth + 1);
            siz[u] += siz[y];
            if(siz[y] > siz[son[u]] || !son[u])
            {
                son[u] = y;
            }
        }
    }
    
    void dfs2(int u,int t)
    {
        top[u] = t;
        id[u] = ++cnt;
        rk[cnt] = u;
        if(!son[u])
            return;
        dfs2(son[u],t);
        for(int k = lst[u];k;k = e[k].nxt)
        {
            int y = e[k].r;
            if(y != son[u] && y != f[u])
                dfs2(y,y);
        }
    }
    
    void push_down(int o,int l,int r)
    {
        if(lazy[o])
        {
            lazy[o << 1] += lazy[o];
            lazy[o << 1] %= p;
            lazy[o << 1 | 1] += lazy[o];
            lazy[o << 1 | 1] %= p;
            int len = (r - l + 1);
            tree[o << 1] += lazy[o] * (len - (len >> 1));
            tree[o << 1 | 1] += lazy[o] * (len >> 1);
            tree[o << 1] %= p;
            tree[o << 1 | 1] %= p;
            lazy[o] = 0;
        }
    }
    
    void build(int o,int l,int r)
    {
        if(l == r)
        {
            tree[o] = a[rk[l]];
            tree[o] %= p;
            return;
        }
        int mid = (l + r) >> 1;
        build(o << 1,l,mid);
        build(o << 1 | 1,mid + 1,r);
        tree[o] = tree[o << 1] + tree[o << 1 | 1];
        tree[o] %= p;
    }
    
    void up_num(int o,int l,int r,int x,int y,int w)
    {
        if(l == x && r == y)
        {
            tree[o] += w * (l - r + 1);
            tree[o] %= p;
            lazy[o] += w;
            lazy[o] %= p;
            return;
        }
        push_down(o,l,r);
        int mid = (l + r) >> 1;
        if(mid < x)
            up_num(o << 1 | 1,mid + 1,r,x,y,w);
        else if(mid >= y)
            up_num(o << 1,l,mid,x,y,w);
        else
        {
            up_num(o << 1,l,mid,x,mid,w);
            up_num(o << 1 | 1,mid + 1,r,mid + 1,y,w);
        }
        tree[o] = tree[o << 1] + tree[o << 1 | 1];
        tree[o] %= p;
    }
    
    int query(int o,int l,int r,int x,int y)
    {
        if(l == r && x == y)
        {
            return tree[o];
        }
        push_down(o,l,r);
        int mid = (l + r) >> 1;
        if(mid >= y)
            return query(o << 1,l,mid,x,y);
        else if(mid < x)
            return query(o << 1 | 1,mid + 1,r,x,y);
        else
        {
            return (query(o << 1,l,mid,x,mid) + query(o << 1 | 1,mid + 1,r,mid + 1,y)) % p;
        }
    }
    
    int pathquery(int x,int y)
    {
        int ans = 0;
        while(top[x] != top[y])
        {
            if(d[top[x]] < d[top[y]])
                swap(x,y);
            ans += query(1,1,n,id[top[x]],id[x]);
            ans %= p;
            x = f[top[x]];
        }
        if(d[x] > d[y])
        swap(x,y);
        ans += query(1,1,n,id[x],id[y]);
        ans %= p;
        return ans;
    }
    
    void pathupdate(int x,int y,int c)
    {
        // int fx = top[x],fy = top[y];
        while(top[x] != top[y])
        {
            if(d[top[x]] < d[top[y]])
            swap(x,y);
            up_num(1,1,n,id[top[x]],id[x],c);
            x = f[top[x]];
            // update(id[x])
        }
        if(d[x] > d[y])
        swap(x,y);
        up_num(1,1,n,id[x],id[y],c);
    }
    int main()
    {
        read(n);read(m);read(r);read(p);
        duke(i,1,n)
        read(a[i]);
        duke(i,1,n - 1)
        {
            int x,y;
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        cnt = 0;
        dfs1(r,0,1);
        dfs2(r,r);
        cnt = 0;
        build(1,1,n);
        duke(i,1,m)
        {
            int op,x,y,z;
            read(op);
            if(op == 1)
            {
                read(x);read(y);read(z);
                pathupdate(x,y,z);
            }
            else if(op == 2)
            {
                read(x);read(y);
                printf("%d
    ",pathquery(x,y));
            }
            else if(op == 3)
            {
                read(x);read(z);
    //            cout<<x<<endl;
                up_num(1,1,n,id[x],id[x] + siz[x] - 1,z);
            }
            else
            {
                read(x);
                printf("%d
    ",query(1,1,n,id[x],id[x] + siz[x] - 1));
            }
        }
        return 0;
    }
    /*
    5 2 24
    3 7 8 0
    2
    5
    1
    1
    4 2
    2 2
    5
    5 1 3
    1 3
    */
  • 相关阅读:
    Serialize and Deserialize Binary Tree
    sliding window substring problem汇总贴
    10. Regular Expression Matching
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接
    程序员如何写一份合格的简历?(附简历模版)
    9个提高代码运行效率的小技巧你知道几个?
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第六章 存储器层次结构
    24张图7000字详解计算机中的高速缓存
    《深入理解计算机系统》(CSAPP)实验四 —— Attack Lab
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第五章 优化程序性能
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9710823.html
Copyright © 2011-2022 走看看