• 浴谷金秋线上集训营 T11738 伪神(树链剖分)


      先树链剖分,一棵子树的编号在数组上连续,一条链用树链剖分,把这些线段全部取出来,做差分,找到有多少点被>=t条线段覆盖即可。

    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    const int maxn=10000010;
    struct poi{int too,pre;}e[maxn<<1];
    int n,m,x,y,z,tot,cnt,ans,a,b,t,cntt;
    int last[maxn],size[maxn],fa[maxn],dep[maxn],son[maxn],w[maxn],top[maxn],mx[maxn],q[maxn],s[maxn];
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    inline void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
    inline void update(int x,int y){q[++cntt]=x;q[++cntt]=y+1;s[x]++;s[y+1]--;}
    void dfs1(int x)
    {
        size[x]=1;
        for(int i=last[x];i;i=e[i].pre)
        {
            int too=e[i].too;
            if(too==fa[x])continue;
            fa[too]=x;
            dep[too]=dep[x]+1;
            dfs1(too);
            if(size[too]>size[son[x]])son[x]=too;
            size[x]+=size[too];
        }
    }
    void dfs2(int x,int tp)
    {
        mx[x]=w[x]=++cnt;top[x]=tp;
        if(son[x])dfs2(son[x],tp),mx[x]=max(mx[x],mx[son[x]]);
        for(int i=last[x];i;i=e[i].pre)
        if(e[i].too!=son[x]&&e[i].too!=fa[x])
        dfs2(e[i].too,e[i].too),mx[x]=max(mx[x],mx[e[i].too]);
    }
    inline void work(int x,int y)
    {
        int f1=top[x],f2=top[y];
        while(f1!=f2)
        {
            if(dep[f1]<dep[f2])swap(x,y),swap(f1,f2);
            update(w[f1],w[x]);
            x=fa[f1];f1=top[x];
        }
        if(dep[x]<dep[y])swap(x,y);
        update(w[y],w[x]);
    }
    int main()
    {
        read(n);read(m);
        for(int i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
        dfs1(1);dfs2(1,1);
        for(int i=1;i<=m;i++)
        {
            read(a);read(b);read(t);cntt=0;
            for(int i=1;i<=a;i++)read(x),read(y),work(x,y);
            for(int i=1;i<=b;i++)read(x),update(w[x],mx[x]);
            q[++cntt]=n+1;q[++cntt]=1;sort(q+1,q+1+cntt);
            cntt=unique(q+1,q+1+cntt)-q-1;
            int sum=0,now=1,ans=0;
            for(int i=1;i<cntt;i++)
            {
                sum+=s[q[i]];
                if(sum>=t)ans+=q[i+1]-q[i];
            }
            for(int i=1;i<=cntt;i++)s[q[i]]=0;
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ARTS第十一周
    ARTS第十周
    ARTS第九周
    一.Java技术现象
    ARTS第八周
    2019书单
    10.枚举的使用
    9.文件输入与输出
    软件模块化设计
    8.String API
  • 原文地址:https://www.cnblogs.com/Sakits/p/7636499.html
Copyright © 2020-2023  润新知