2017沈阳网络赛ping (树链剖分+树状数组)

来源:互联网 发布:matlab读取excel数据 编辑:程序博客网 时间:2024/05/22 04:42

  标准对树进行树链剖分,并用树状数组维护连续区间和问题。树状数组维护两点u,v对应的【tid【u】,tid【v】】区间是否有点已经被破坏。

  代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define n 10005
const int maxn=50000+5;
vector<int>p[n];
int in[n],out[n],dep[n],fa[n];
int son[n],siz[n],tep[n],c[n],tot,nn;
struct node{
    int u,v,lca;
    friend bool operator<(node n1,node n2){
        return dep[n1.lca]<dep[n2.lca];
    }
}g[maxn];
bool cmp(node a,node b){
    return b<a;
}
void addedge(int u,int v){
    p[u].push_back(v);
    p[v].push_back(u);
}
void init(int x){
    tot=0;
    for (int i=1; i<=x+1;i++){
        son[i]=-1;
        siz[i]=1;
        p[i].clear();
        c[i]=0;
    }
}
void dfs1(int u,int father,int dp){
    in[u]=++tot;
    dep[u]=dp;
    fa[u]=father;
    for (int i=0; i<p[u].size(); i++) {
        int v=p[u][i];
        if (v!=father) {
            dfs1(v, u, dp+1);
            siz[u]+=siz[v];
            if (son[u]==-1||siz[son[u]]<siz[v]) {
                son[u]=v;
            }
        }
    }
    out[u]=tot;
}
void dfs2(int u,int tp){
    tep[u]=tp;
    if (son[u]==-1) {
        return;
    }
    dfs2(son[u], tp);
    for (auto v:p[u]) {
        if (v==fa[u]||v==son[u]) {
            continue;
        }
        dfs2(v, v);
    }
}
int lca(int u,int v){
    while (tep[u]!=tep[v]) {
        if (dep[tep[u]]<dep[tep[v]]) {
            swap(u, v);
        }
        u=fa[tep[u]];
    }
    if (dep[u]>dep[v]) {
        swap(u, v);
    }
    return u;
}
int lowbit(int x){
    return x&(-x);
}
int sum(int x){
    int ans=0;
    while (x) {
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
void change(int x,int y){
    while (x<n) {
        c[x]+=y;
        x+=lowbit(x);
    }
}
int main(){
    while (scanf("%d",&nn)!=EOF) {
        init(nn);
        for (int i=0; i<nn; i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            u++;v++;
            addedge(u,v);
        }
        nn++;
        dfs1(1, -1, 1);
        dfs2(1, 1);
        int q;
        cin>>q;
        for (int i=0; i<q; i++) {
            scanf("%d%d",&g[i].u,&g[i].v);
            g[i].u++;g[i].v++;
            g[i].lca=lca(g[i].u, g[i].v);
        }
        sort(g,g+q,cmp);
        int ans=0;
        for (int i=0; i<q; i++) {
            int u=g[i].u,v=g[i].v,lc=g[i].lca;
            int num=sum(in[u])+sum(in[v]);
            if (!num) {
                ans++;
                change(in[lc],1);
                change(out[lc]+1,-1);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

原创粉丝点击