1. 题目

传送门= ̄ω ̄=

题意:

I C1 C2 K: 把 C1 与 C2 的路径上的所有点权值加上 K

D C1 C2 K:把 C1 与 C2 的路径上的所有点权值减去 K

Q C:查询节点编号为 C 的权值

有多组数据,n<=50000

2. 题解

树链剖分模板题
树剖以后用线段树维护即可
然而智障的我老是区间加的标记不用+=而用=导致 WA

代码:

#include <bits/stdc++.h>
#define NS (50005)
#define LS(a) (a<<1)
#define RS(a) ((a<<1)|1)
using namespace std;
struct N{int l,r,d,f;N(){l=r=d=f=0;}}e[NS<<2];
int n,p,arr[NS],w[NS],fa[NS],dep[NS],siz[NS],pos[NS],top[NS],cnt;
char opt[10];
vector<int> g[NS];
void update(int a){e[a].d=e[LS(a)].d+e[RS(a)].d;}
void pdown(int a)
{
    e[LS(a)].d+=e[a].f*(e[LS(a)].r-e[LS(a)].l+1);
    e[RS(a)].d+=e[a].f*(e[RS(a)].r-e[RS(a)].l+1);
    e[LS(a)].f+=e[a].f,e[RS(a)].f+=e[a].f,e[a].f=0;
}
void build(int l,int r,int a)
{
    e[a].l=l,e[a].r=r,e[a].f=0;
    if(l==r){e[a].d=w[l];return;}
    build(l,(l+r)>>1,LS(a)),build(((l+r)>>1)+1,r,RS(a)),update(a);
}
void change(int l,int r,int k,int a)
{
    if(l<=e[a].l&&e[a].r<=r){e[a].d+=(e[a].r-e[a].l+1)*k,e[a].f+=k;return;}
    if(e[a].f)pdown(a);
    if(l<=((e[a].l+e[a].r)>>1))change(l,r,k,LS(a));
    if(r>((e[a].l+e[a].r)>>1))change(l,r,k,RS(a));
    update(a);
}
int query(int x,int a)
{
    if(e[a].l==x&&e[a].r==x)return e[a].d;
    if(e[a].f)pdown(a);
    if(x<=((e[a].l+e[a].r)>>1))return query(x,LS(a));
    return query(x,RS(a));
}
void dfs1(int u)
{
    dep[u]=dep[fa[u]]+1,siz[u]=1;
    for(int i=0;i<g[u].size();i++)
        if(g[u][i]!=fa[u])fa[g[u][i]]=u,dfs1(g[u][i]),siz[u]+=siz[g[u][i]];
}
void dfs2(int u)
{
    int nxt=0,maxn=0;pos[u]=cnt++;
    for(int i=0;i<g[u].size();i++)
        if(g[u][i]!=fa[u]&&siz[g[u][i]]>maxn)nxt=g[u][i],maxn=siz[g[u][i]];
    if(!nxt)return;
    top[nxt]=top[u],dfs2(nxt);
    for(int i=0;i<g[u].size();i++)
        if(g[u][i]!=fa[u]&&g[u][i]!=nxt)top[g[u][i]]=g[u][i],dfs2(g[u][i]);
}
void work(int a,int b,int c)
{
    while(top[a]!=top[b])
    {
        if(dep[top[a]]>dep[top[b]])swap(a,b);
        change(pos[top[b]],pos[b],c,1),b=fa[top[b]];
    }
    if(pos[a]>pos[b])swap(a,b);
    change(pos[a],pos[b],c,1);
}
int main()
{
    while(cnt=0,~scanf("%d%d%d",&n,&p,&p))
    {
        for(int i=1;i<=n;i++)scanf("%d",&arr[i]),g[i].clear();
        for(int i=1,a,b;i<n;i++)
            scanf("%d%d",&a,&b),g[a].push_back(b),g[b].push_back(a);
        dfs1(1),top[1]=1,dfs2(1);
        for(int i=1;i<=n;i++)w[pos[i]]=arr[i];
        build(0,cnt-1,1);
        for(int i=1,a,b,c;i<=p;i++)
        {
            scanf("%s%d",opt,&a);
            if(opt[0]=='I')scanf("%d%d",&b,&c),work(a,b,c);
            else if(opt[0]=='D')scanf("%d%d",&b,&c),work(a,b,-c);
            else printf("%d\n",query(pos[a],1));
        }
    }
    return 0;
}
分类: 文章

XZYQvQ

炒鸡辣鸡的制杖蒟蒻一枚QvQ

2 条评论

boshi · 2017年6月30日 9:33 下午

You seem to have much more point that I have no salt to right.

konnyakuxzy · 2017年6月30日 8:10 下午

You seem to have a point
但是我懒得再开一个数组了

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注