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\n",id[i],tp[i]);*/
//    printf("QAQ\n");
    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\n",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\n",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\n",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
*/

 

posted @ 2018-09-26 23:46  DukeLv  阅读(152)  评论(0编辑  收藏  举报