absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] 575B
[破碎的状态] BZOJ 1051

[破碎的状态] 575B-树链剖分

absi2011 posted @ Apr 18, 2016 09:11:10 AM in 刷题记录 with tags 小高考 LCA CF 树链剖分 , 487 阅读

似乎树链剖分直接写会T

思考了一发,树链剖分的精髓在于剖分而不是线段树维护..所以我就差分维护了一发..

然后..就过了..

题意:http://absi2011.is-programmer.com/posts/199147.html

代码:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct edge
{
    int y;
    int weight;
    edge * next;
};
edge * li[100005];
edge * new_edge()
{
    static edge a[200005];
    static int top=0;
    return &a[top++];
}
void inserts(int x,int y,int z)
{
    edge * t=new_edge();
    t->y=y;
    t->weight=z;
    t->next=li[x];
    li[x]=t;
}
void insert_edge(int x,int y,int z)
{
    inserts(x,y,0);
    inserts(y,x,z);
}
int l0,r0;
int val[2][1<<20];
int dfn[100005];
int depth[100005];
int size[100005];
int father[100005];
int up[100005];
int unok[100005][2];
edge * max_weight[100005];
void dfs1(int x)
{
    edge * t;
    size[x]=1;
    for (t=li[x];t!=0;t=t->next)
    {
        if (t->y!=father[x])
        {
            father[t->y]=x;
            depth[t->y]=depth[x]+1;
            dfs1(t->y);
            size[x]+=size[t->y];
            unok[t->y][1]=t->weight;
        }
        else
        {
            unok[x][0]=t->weight;
        }
    }
    int max_now=0;
    for (t=li[x];t!=0;t=t->next)
    {
        if (t->y!=father[x])
        {
            if (size[t->y]>max_now)
            {
                max_now=size[t->y];
                max_weight[x]=t;
            }
        }
    }
}
void dfs2(int x)
{
    static int top=0;
    dfn[x]=top++;
    if (max_weight[x]!=0)
    {
        up[max_weight[x]->y]=up[x];
        dfs2(max_weight[x]->y);
    }
    edge * t;
    for (t=li[x];t!=0;t=t->next)
    {
        if (t->y==father[x]) continue;
        if (t==max_weight[x]) continue;
        up[t->y]=t->y;
        dfs2(t->y);
    }
}
int lca(int x,int y)
{
    for (;;)
    {
        if (depth[up[x]]<depth[up[y]]) swap(x,y);
        if (up[x]==up[y])
        {
            if (depth[x]<depth[y]) swap(x,y);
            return y;
        }
        x=up[x];
        x=father[x];
    }
}
const int modo=1000000007;
int power2[1000005];
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    fprintf(stderr,"%d\n",clock());
    #endif
    int n;
    scanf("%d",&n);
    int i;
    power2[0]=0;
    for (i=1;i<=1000001;i++)
    {
        power2[i]=(power2[i-1]*2+1)%modo;
    }
    for (i=1;i<n;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        x--;
        y--;
        insert_edge(x,y,z);
    }
    memset(father,-1,sizeof(father));
    dfs1(0);
    dfs2(0);
    int m;
    scanf("%d",&m);
    int last;
    last=0;
    for (i=0;i<m;i++)
    {
        int now;
        scanf("%d",&now);
        now--;
        int x=last,y=now;
        last=now;
        int z=lca(x,y);
        int k=0;
        for (;;)
        {
            if (up[x]==up[z])
            {
                l0=dfn[z];
                r0=dfn[x];
                val[k][r0]++;
                val[k][l0]--;
                break;
            }
            else
            {
                l0=dfn[up[x]];
                r0=dfn[x];
                val[k][r0]++;
                val[k][l0-1]--;
            }
            x=father[up[x]];
        }
        k=1;
        for (;;)
        {
            if (up[y]==up[z])
            {
                l0=dfn[z];
                r0=dfn[y];
                val[k][r0]++;
                val[k][l0]--;
                break;
            }
            else
            {
                l0=dfn[up[y]];
                r0=dfn[y];
                val[k][r0]++;
                val[k][l0-1]--;
            }
            y=father[up[y]];
        }
    }
    int sum=0;
    for (i=n-1;i>=0;i--)
    {
        val[0][i]+=val[0][i+1];
        val[1][i]+=val[1][i+1];
    }
    for (i=1;i<n;i++)
    {
        if (unok[i][0]) sum+=power2[val[0][dfn[i]]];
        if (sum>=modo) sum-=modo;
        if (unok[i][1]) sum+=power2[val[1][dfn[i]]];
        if (sum>=modo) sum-=modo;
    }
    printf("%d\n",sum);
    #ifdef absi2011
    fprintf(stderr,"%d\n",clock());
    #endif
    return 0;
}

登录 *


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