Acdream 1424 树链剖分

还是做的少,都完全不知道往树链剖分方向想,赛后听了昂神思路才恍然。

首先,石头路连接构成的是一棵树,然后,对于泥路,可以看作是在它的期末位置所在链上覆盖,被覆盖到两次的石头路都是破坏后不能达到效果的,而对于只被覆盖过1次的石头路则是可以的,这条路被断后,剩下一个要断的土路即为覆盖它的那条。所以,只要树链剖分一下,记录被覆盖次数,然后找出只被覆盖了一次的个数即为答案。

#include
#include
#include
#include
#include
using namespace std;
struct node
{
    int l,r,a;
}t[88888];
vectorg[22222];
int f[22222],top[22222],w[22222],s[22222];
int dep[22222],son[22222];
int m,n,sz;
int qx[222222],qy[222222],qnum;
void dfs1(int u)
{
    s[u]=1;
    son[u]=0;
    for(int i=0;is[son[u]])son[u]=v;
    }
}
void dfs2(int u,int ff)
{
    top[u]=ff;
    w[u]=++sz;
    if(son[u])dfs2(son[u],ff);
    for(int i=0;irr)return;
    if(t[rot].l==ll&&t[rot].r==rr)
    {
        t[rot].a++;
        return;
    }
    if(t[rot].a)
    {
        t[rot<<1].a+=t[rot].a;
        t[rot<<1|1].a+=t[rot].a;
        t[rot].a=0;
    }
    int mid=(t[rot].l+t[rot].r)/2;
    if(rr<=mid)update(ll,rr,rot<<1);
    else if(ll>mid)update(ll,rr,rot<<1|1);
    else
    {
        update(ll,mid,rot<<1);
        update(mid+1,rr,rot<<1|1);
    }
}
void solve(int u,int v)
{
    int uu=top[u];
    int vv=top[v];
    while(uu!=vv)
    {
        if(dep[u]>dep[v])
        {
            swap(u,v);
            swap(uu,vv);
        }
        update(w[vv],w[v],1);
        v=f[vv];
        vv=top[v];
    }
    if(dep[u]>dep[v])swap(u,v);
    update(w[son[u]],w[v],1);
}
int query(int rot)
{
    if(t[rot].l==t[rot].r)
    {
        if(t[rot].a==1)return 1;
        else return 0;
    }
    if(t[rot].a)
    {
        t[rot<<1].a+=t[rot].a;
        t[rot<<1|1].a+=t[rot].a;
        t[rot].a=0;
    }
    return query(rot<<1)+query(rot<<1|1);
}
int main()
{
    int u,v,c;
    scanf("%d%d",&n,&m);
    sz=0;
    qnum=0;
    for(int i=0;i


你可能感兴趣的:(acm,Baoge)