absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] [-2] 模拟退火
[破碎的状态] [-2] Vijos 1951

[破碎的状态] [-2] BZOJ 4034

absi2011 posted @ Jul 20, 2016 04:33:18 PM in 刷题记录 with tags 小高考 bzoj 树链剖分 , 350 阅读

这是一道树链剖分的水题..

代码:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<sstream>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int a[100005];
struct edge
{
    int y;
    edge * next;
};
edge * new_edge()
{
    static edge a[200005];
    static int top=0;
    return &a[top++];
}
edge * li[100005];
void inserts(int x,int y)
{
    edge * t=new_edge();
    t->y=y;
    t->next=li[x];
    li[x]=t;
}
void insert_edge(int x,int y)
{
    inserts(x,y);
    inserts(y,x);
}
const int maxn=100005;
int depth[maxn];
int size[maxn];
int father[maxn];
int up[maxn];
edge * prefer_edge[maxn];
void dfs1(int x)
{
    edge * t;
    size[x]=1;
    int max_size=0;
    for (t=li[x];t!=0;t=t->next)
    {
        if (t->y==father[x]) continue;
        depth[t->y]=depth[x]+1;
        father[t->y]=x;
        dfs1(t->y);
        size[x]+=size[t->y];
        if (max_size<size[t->y])
        {
            max_size=size[t->y];
            prefer_edge[x]=t;
        }
    }
}
int vis[maxn];
int dfn[maxn];
void dfs2(int x)
{
    static int num=0;
    dfn[x]=num;
    vis[num]=x;
    num++;
    if (prefer_edge[x]==0) return;
    up[prefer_edge[x]->y]=up[x];
    dfs2(prefer_edge[x]->y);
    edge * t;
    for (t=li[x];t!=0;t=t->next)
    {
        if (t->y==father[x]) continue;
        if (t==prefer_edge[x]) continue;
        up[t->y]=t->y;
        dfs2(t->y);
    }
}
long long val[1<<18];
long long tag[1<<18];
void build_tree(int num,int l,int r)
{
    if (l==r-1)
    {
        val[num]=a[vis[l]];
        tag[num]=0;
        return;
    }
    int mid=(l+r)/2;
    build_tree(num*2+1,l,mid);
    build_tree(num*2+2,mid,r);
    tag[num]=0;
    val[num]=val[num*2+1]+val[num*2+2];
}
void change(int num,int l,int r,int l0,int r0,int k)
{
    if ((l0<=l)&&(r<=r0))
    {
        val[num]+=(long long)k*(r-l);
        tag[num]+=k;
        return;
    }
    int mid=(l+r)/2;
    if (l0<mid) change(num*2+1,l,mid,l0,r0,k);
    if (mid<r0) change(num*2+2,mid,r,l0,r0,k);
    val[num]=val[num*2+1]+val[num*2+2]+(r-l)*tag[num];
}
long long query(int num,int l,int r,int l0,int r0)
{
    if ((l0<=l)&&(r<=r0))
    {
        return val[num];
    }
    int mid=(l+r)/2;
    long long sum=0;
    if (l0<mid) sum+=query(num*2+1,l,mid,l0,r0)+tag[num]*(min(r0,mid)-max(l,l0));
    if (mid<r0) sum+=query(num*2+2,mid,r,l0,r0)+tag[num]*(min(r0,r)-max(mid,l0));
    return sum;
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,m;
    scanf("%d%d",&n,&m);
    int i;
    for (i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    for (i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x--;
        y--;
        insert_edge(x,y);
    }
    father[0]=-1;
    up[0]=0;
    depth[0]=0;
    dfs1(0);
    dfs2(0);
    build_tree(0,0,n);
    for (i=0;i<m;i++)
    {
        int oper;
        scanf("%d",&oper);
        if (oper==1)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x--;
            change(0,0,n,dfn[x],dfn[x]+1,y);
        }
        else if (oper==2)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x--;
            change(0,0,n,dfn[x],dfn[x]+size[x],y);
        }
        else
        {
            int x;
            scanf("%d",&x);
            x--;
            long long ans=0;
            for (;;)
            {
                ans+=query(0,0,n,dfn[up[x]],dfn[x]+1);
                x=father[up[x]];
                if (x==-1) break;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter