zoukankan      html  css  js  c++  java
  • 【Luogu】P3806点分治模板(点分治)

      题目链接

      wc听不懂lca讲的高等数学专场(一个字都听不懂),然后就自学了点分治。

      点分治就是我先处理完跟根有关的东西,然后把根标记掉,把原树拆成若干个联通块,然后分别对每个联通块(每个小树)搞一模一样的操作。

      然后要每次求重心,因为点分治复杂度跟递归深度有关。

      本题判断的时候偷懒用map,其实自己写的splay也快不到哪里去的样子。qwq。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #include<map>
    #define maxn 200020
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int next,to,val;
    }edge[maxn*3];
    int head[maxn],num;
    inline void add(int from,int to,int val){
        edge[++num]=(Edge){head[from],to,val};
        head[from]=num;
    }
    
    map<int,bool>ext;
    
    bool tag[maxn];
    int size[maxn];
    int mxn[maxn];
    int stack[maxn],top;
    int d[maxn];
    int w[maxn];
    int root=0;
    
    void getroot(int x,int fa,int lim){
        int ret=0;size[x]=1;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa||tag[to])    continue;
            getroot(to,x,lim);
            size[x]+=size[to];
            if(ret<size[to])    ret=size[to];
        }
        if(ret<lim-size[x])    ret=lim-size[x];
        mxn[x]=ret;
        if(ret<mxn[root]||root==0)    root=x;
    }
    
    void depfind(int x,int fa,int dst){
        stack[++top]=dst;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa||tag[to])    continue;
            depfind(to,x,dst+edge[i].val);
        }
        return;
    }
    
    int getsize(int x,int fa){
        int ans=1;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa||tag[to])    continue;
            ans+=getsize(to,x);
        }
        return ans;
    }
    
    void dfs(int x,int lim,int m){
        root=0;
        getroot(x,x,lim);
        tag[root]=1;
        ext.clear();ext[0]=1;
        for(int i=head[root];i;i=edge[i].next){
            int to=edge[i].to;
            if(tag[to])    continue;
            top=0;
            depfind(to,to,edge[i].val);
            sort(stack+1,stack+top+1);
            for(int j=1;j<=m;++j){
                if(w[j])    continue;
                for(int k=1;k<=top;++k){
                    int now=d[j]-stack[k];
                    if(ext[now]==1)    w[j]=1;
                }
            }
            for(int j=1;j<=top;++j)    ext[stack[j]]=1;
        }
        int now=root;
        for(int i=head[now];i;i=edge[i].next){
            int to=edge[i].to;
            if(tag[to])    continue;
            int ret=getsize(to,to);
            dfs(to,ret,m);
        }
    }
    
    int main(){
        int n=read(),m=read();
        for(int i=1;i<n;++i){
            int x=read(),y=read(),z=read();
            add(x,y,z);
            add(y,x,z);
        }
        for(int i=1;i<=m;++i)    d[i]=read();
        dfs(1,n,m);
        for(int i=1;i<=m;++i)
            if(w[i]==1)    printf("AYE
    ");
            else        printf("NAY
    ");
        return 0;
    }
    /*
    13 10
    1 2 1
    1 4 2
    4 3 5
    4 5 11
    5 6 4
    5 7 2
    4 8 7
    1 10 2
    9 10 9
    1 11 4
    11 13 5
    11 12 6
    12
    11
    10
    9
    8
    22
    13
    14
    15
    18
    */
  • 相关阅读:
    CSS_行内元素和块级元素
    jdbc连接oracle11g的问题——查不出来数据,权限问题
    新的起点
    MVC过滤器详解
    SQL Server游标的使用
    处理百万级以上的数据提高查询速度的方法
    两个有序数组找出相同数据
    C# 可变参数
    C#反射
    产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复。
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8419515.html
Copyright © 2011-2022 走看看