首页 > 其他分享 >点分治

点分治

时间:2023-06-07 21:15:12浏览次数:20  
标签:const int MAX 分治 ret tf inf

询问树上距离为 k 的点对是否存在。

#include<bits/stdc++.h>
using namespace std;
const int MAX=20010;
const int inf=1.5e8;
int n,m,x,y,z,q[MAX],rt,siz[MAX],maxx[MAX],dis[MAX];
vector<pair<int,int> >g[MAX];
stack<int>tag;
bool tf[inf],ret[MAX],vis[MAX];
int sum,d[MAX],cnt;
inline int read(){
    int x=0;char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c<='9'&&c>='0'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    return x;
} 
void zx(int,int);
void csiz(int,int);
void cdis(int,int);
void dfs(int,int);
int main(){
    n=read();m=read();
    for(int i=1;i<n;++i){
        x=read();y=read();z=read();
        g[x].push_back(make_pair(y,z));
        g[y].push_back(make_pair(x,z));
    }for(int i=1;i<=m;++i)  q[i]=read();
    maxx[rt=0]=MAX;sum=n;tf[0]=1;tag.push(0);
    zx(1,-1);csiz(rt,-1);dfs(rt,-1);
    for(int i=1;i<=m;++i)
        if(ret[i])  printf("AYE\n");
        else  printf("NAY\n");
}
void zx(int u,int fa){
    siz[u]=1;maxx[u]=0;
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i].first;
        if(v!=fa&&!vis[v]){
            zx(v,u);siz[u]+=siz[v];
            maxx[u]=max(maxx[u],siz[v]);
        }
    }maxx[u]=max(maxx[u],sum-maxx[u]);
    if(maxx[u]<maxx[rt])  rt=u;
}void csiz(int u,int fa){
    siz[u]=1;
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i].first;
        if(v!=fa&&!vis[v]){
            csiz(v,u);siz[u]+=siz[v];
        }
    }
}void cdis(int u,int fa){
    d[++cnt]=dis[u];
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i].first;
        if(v!=fa&&!vis[v]){
            dis[v]=dis[u]+g[u][i].second;cdis(v,u);
        }
    }
}
void dfs(int u,int fa){
    vis[u]=1;
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i].first;
        if(v!=fa&&!vis[v]){
            dis[v]=g[u][i].second;
            cnt=0;cdis(v,u);
            for(int j=1;j<=cnt;++j)
                for(int k=1;k<=m;++k)
                    if(q[k]>=d[j])  ret[k]|=tf[q[k]-d[j]];
            for(int j=1;j<=cnt;++j)  tag.push(d[j]),tf[d[j]]=1;
        }
    }while(tag.top())  tf[tag.top()]=0,tag.pop();
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i].first;
        if(v!=fa&&!vis[v]){
            maxx[rt=0]=MAX;sum=siz[v];
            zx(v,u);csiz(rt,-1);dfs(rt,-1);
        }
    }
}
View Code

 

标签:const,int,MAX,分治,ret,tf,inf
From: https://www.cnblogs.com/yswn/p/17464555.html

相关文章

  • Codeforces 1566G - Four Vertices(线段树分治)
    交了整整2页,本来想用随机化卡过去的,后来发现我的实现跑得太慢就写正常做法了。首先发现最优答案对应的四个点只可能有以下两种可能:\(a,b\)间有边,\(c,d\)间有边,此时答案是\(a,b\)边权值加\(c,d\)边权值。\(a\)与\(b,c,d\)三个点间都有边,此时答案是三条边权值之和。......
  • 用分治处理决策单调性问题
    决策单调性是dp转移方程的一种性质。一般而言,我们有许多方法优化一个具有决策单调性的转移方程。这里主要讲解一种用分治解决决策单调性问题的方法。引入先看一道题:CF868F我们可以想到一个\(O(n^2k)\)暴力。定义\(dp_{i,j}\)为令点\(i\)为第\(j\)段的最后一个点产......
  • 分治
    分治法基本介绍分治法,即“分而治之”,对于一个难以解决的大问题,将其分解成k个相同或相似的规模更小的子问题,一直分解直到问题足够小,极容易求解为止。解题步骤分治法建模的大概流程可以分为三步:1.分解:将大问题分解成多个更小的独立且相同或相似子问题,直到子问题容易容易求解2.......
  • 「学习笔记」略谈点分治
    点分治适合处理大规模的树上路径信息问题。引入给定一棵\(n\)个点树和一个整数\(k\),求树上两点间的距离小于等于\(k\)的点对有多少。对于这个题,如果我们进行\(O_{n^3}\)搜索,那只要\(n\)一大,铁定超时。所以,我们要用一个更优秀的解法,这就是我们的点分治。淀粉质可......
  • 不同路径 II(数组、动态规划)、同构字符串(哈希表、字符串)、颠倒二进制位(位运算、分
    不同路径II(数组、动态规划)一个机器人位于一个_mxn_网格的左上角(起始点在下图中标记为“Start”)。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网......
  • Summary - 分治
    本文旨在总结数种分治算法。1.区间分治:当需要对所有区间统计答案时,可以考虑这种分治。具体来说,在处理\([l,r]\)内的所有区间时,分三类考虑:跨过\(mid\)的,完全在\(mid\)左边的,完全在\(mid\)右边的。如果可以\(O(m)\)或\(O(m\logm)\)处理第一类情形(\(m=r-l+1\)),然后用分治处理另外两......
  • Solution Set - CDQ分治
    A[洛谷P2163].给定平面上若干个点,多次询问给定矩形内的点数。B[洛谷P3810].给定若干个三元组,对所有\(k\),求这样三元组的个数:恰有\(k\)个三元组,满足其每个分量都不超过它的相应分量。C[洛谷P3157].给定一个序列,从中依次删去某些元素,求每次删除前逆序对数目。D[CF762E/CF1045G].......
  • Solution Set - 点分治
    A[POJ1741].给定一棵树,边有权,求长度不超过\(k\)的路径数目。B[HDU4871].给定一张图,边有权,求它的最短路径树上恰含\(k\)个点的路径中最长路径的长度及数目。C[HDU4812].给定一棵树,点有权,求字典序最小的一个点对,其路径上的所有点权之积模\(100003\)等于\(k\)。D[HDU5469].给定一......
  • 点分治学习笔记
    概念点分治用于解决有一定要求的链的计数。对于点\(u\)的子树的问题,可以将答案分为:经过点\(u\)不经过点\(u\)第一种可以用桶加暴力。枚举一端的长度,用桶计算另一端长度;第二种分到子树中解决即可。注意到,在随机选根的时候该算法表现不优秀,但若根为重心,因为每次子树......
  • 树分治学习笔记
    前言既然序列可以分治,那么树也可以分治。树上的分治可以分为点分治与边分治。点分治边分治主要用于处理树上路径问题。考虑一个分治的过程:选中一棵树的根,计算经过根的路径的贡献,然后以其子结点为根对子树递归地计算贡献。容易发现,在构造数据下这种算法的复杂度是可以达到\(O(......