ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【模板】P3806点分治1

2019-02-08 17:00:59  阅读:271  来源: 互联网

标签:路径 RP int 分治 P3806 now sav 模板


【模板】P3806 【模板】点分治1

很好的一道模板题,很无脑经典。

讲讲淀粉质吧,很营养,实际上,点分治是树上的分治算法。根据树的特性,树上两点的路径只有一下两种情况:

  • 路径经过根\((*)\)
  • 路径不经过根\((**)\)

显然对于\((**)\)我们可以通过指定一个新的根使得\((**)\)变成一个子问题。

那么我们在处理的时候,分两种情况:

  • 处理自己各个子树之间的路径\((-)\)
  • 各个子树之内的路径\((--)\)

显然\((--)\)的问题可以通过递归\((**)\)的子问题解决

那么有什么用呢?

考虑时间复杂度,我们指定新根时,若制定它的各自子树的重心,那么最多会递归\(logn​\)次。这是淀粉质的营养时间基数。

那么,我们只需要设计在子树间进行统计答案的复杂度为\(O(x)​\)的算法,那么我们就可以做到\(O(xlogn)​\)的解决了。

这道模板题是问我们是否存在路径长度为\(k\)的路径,我们直接开桶把一个点到指定的\(rt\)的距离存下来,之后直接查询即可,这样的时间复杂度是\(O(n)\)。

总时间复杂度\(O(nlogn)\)

代码如下

#include<bits/stdc++.h>

using namespace std;
#define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
#define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
#define ERP(t,a) for(register int t=head[a];t;t=e[t].nx)
#define Max(a,b) ((a)<(b)?(b):(a))
#define Min(a,b) ((a)<(b)?(a):(b))
#define midd register int mid=(l+r)>>1
#define TMP template < class ccf >

TMP inline ccf qr(ccf b){
    char c=getchar();
    int q=1;
    ccf x=0;
    while(c<48||c>57)
    q=c==45?-1:q,c=getchar();
    while(c>=48&&c<=57)
    x=x*10+c-48,c=getchar();
    return q==-1?-x:x;
}
const int maxn=1e4+15;
int n,m;
struct E{
    int to,w,nx;
}e[maxn<<1];
int head[maxn];
int cnt;
inline void add(int fr,int to,int w,bool f){
    e[++cnt]=(E){to,w,head[fr]};
    head[fr]=cnt;
    if(f)
    add(to,fr,w,0);
}
bool usd[maxn];
int siz[maxn];
int spa[maxn];
int sav[maxn];
int d[maxn];
int rt;
int k[105];
bool ans[10000005];
bool tell[105];
int q[maxn];
int sum;


void dfsroot(int now,int last){
    siz[now]=1;
    spa[now]=0;
    ERP(t,now){
    if(e[t].to!=last&&!usd[e[t].to]){
        dfsroot(e[t].to,now);
        siz[now]+=siz[e[t].to];
        spa[now]=Max(spa[now],siz[e[t].to]);
    }
    }
    spa[now]=Max(spa[now],sum-siz[now]);
    if(spa[now]<spa[rt]||rt==0)
    rt=now;
}


void dfsdis(int now,int last,int ew){
    d[now]=d[last]+ew;
    sav[++sav[0]]=d[now];
    ERP(t,now){
    if(e[t].to!=last&&!usd[e[t].to]){
        dfsdis(e[t].to,now,e[t].w);
    }
    }
}

inline void calc(int now){
    register int p=0;
    ERP(t,now){
    if(!usd[e[t].to]){
        sav[0]=0;d[now]=0;
        dfsdis(e[t].to,now,e[t].w);
        RP(j,1,m){
        if(!tell[j]){
            RP(i,1,sav[0]){
            if(k[j]>=sav[i]){
                if(ans[k[j]-sav[i]])
                tell[j]=1;
            }
            }
        }
        }
        RP(i,1,sav[0])
        ans[sav[i]]=1;
        RP(i,1,sav[0])
        q[++p]=sav[i];
    }
    }
    
    RP(t,1,p)
    ans[q[t]]=0;
}

void solve(int now){
    usd[now]=ans[0]=1;
    calc(now);
    ERP(t,now){
    if(!usd[e[t].to]){
        sum=siz[e[t].to];
        rt=0;
        dfsroot(e[t].to,0);
        solve(rt);
    }
    }
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
#endif
    
    n=qr(1);
    m=qr(1);
    for(register int t=1,t1,t2,t3;t<n;++t){
    t1=qr(1);
    t2=qr(1);
    t3=qr(1);
    add(t1,t2,t3,1);
    }
    RP(t,1,m)
    k[t]=qr(1),tell[t]=!k?1:0;
    sum=n;
    dfsroot(1,0);
    solve(rt);
    
    RP(t,1,m)
    if(tell[t])
        puts("AYE");
    else
        puts("NAY");
    return 0;
    
}

标签:路径,RP,int,分治,P3806,now,sav,模板
来源: https://www.cnblogs.com/winlere/p/10356368.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有