点分治

点分治

询问树上距离为 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
复制代码

 

点分树

震波

复制代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
int n,m,val[MAX],maxx,rt,siz[MAX],dep[MAX],fa[MAX],sum;
int vis[MAX];
int in[MAX],chuo,ol[MAX<<1][22];
vector<int>g[MAX],c[2][MAX];
int opt,x,y,ans;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c<='9'&&c>='0'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    return x*f;
}void dfs(int,int,int);
inline void init();
inline int qu(int,int);
void zx(int,int);
void csiz(int,int);
void dfs1(int);
inline int lowbit(int x){return x&-x;}
inline void add(int op,int u,int x,int v){
    x++;
    while(x<=siz[u]+op)  c[op][u][x]+=v,x+=lowbit(x);//+op
}inline int query(int op,int u,int x){
    x=min(x+1,siz[u]+op);int ans=0;
    while(x)  ans+=c[op][u][x],x-=lowbit(x);
    return ans;
}inline void upda(int u,int v){
    for(int i=u;i;i=fa[i])  add(0,i,qu(u,i),v);
    for(int i=u;fa[i];i=fa[i])  add(1,i,qu(u,fa[i]),v);
}
int main(){
    //freopen("1.txt","r",stdin); 
    n=read();m=read();
    for(int i=1;i<=n;++i)  val[i]=read();
    for(int i=1;i<n;++i){
        x=read();y=read();
        g[x].push_back(y);g[y].push_back(x);
    }dfs(1,0,0);init();maxx=sum=n;
    zx(1,-1);csiz(rt,-1);dfs1(rt);
    for(int i=1;i<=n;++i)  upda(i,val[i]);
    while(m--){
        opt=read();x=read()^ans;y=read()^ans;
        if(opt==0){
            ans=query(0,x,y);
            for(int i=x;fa[i];i=fa[i]){
                int dis=qu(x,fa[i]);
                if(y>=dis)  ans+=query(0,fa[i],y-dis)-query(1,i,y-dis);
            }printf("%d\n",ans);
        }else{
            upda(x,y-val[x]);val[x]=y;
        }
    }
}
void dfs(int u,int fa,int d){
    ol[++chuo][0]=u;dep[u]=d;
    in[u]=chuo;
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i];
        if(v^fa)  dfs(v,u,d+1),ol[++chuo][0]=u;
    }
}inline void init(){
    for(int j=1;(1<<j)<=chuo;++j)
        for(int i=1;i+(1<<j)-1<=chuo;++i)
            ol[i][j]=dep[ol[i][j-1]]>dep[ol[i+(1<<(j-1))][j-1]]?ol[i+(1<<(j-1))][j-1]:ol[i][j-1];
}inline int qu(int l,int r){
    if(in[l]>in[r])  swap(l,r);
    int k=log2(in[r]-in[l]+1),lca;//
    lca=dep[ol[in[l]][k]]>dep[ol[in[r]-(1<<k)+1][k]]?ol[in[r]-(1<<k)+1][k]:ol[in[l]][k];
    return dep[l]+dep[r]-dep[lca]*2;
}
void zx(int u,int fa){
    siz[u]=1;int m1=0;
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i];
        if(v^fa&&!vis[v]){
            zx(v,u);siz[u]+=siz[v];
            m1=max(m1,siz[v]);
        }
    }m1=max(m1,sum-siz[u]);
    if(m1<maxx){rt=u;maxx=m1;}
}void csiz(int u,int fa){
    siz[u]=1;
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i];
        if(v^fa&&!vis[v]){
            csiz(v,u);siz[u]+=siz[v];
        }
    }
}void dfs1(int u){
    vis[u]=1;
    c[0][u].resize(siz[u]+2);
    c[1][u].resize(siz[u]+2);
    for(int i=0;i<g[u].size();++i){
        int v=g[u][i];
        if(!vis[v]){
            maxx=sum=siz[v];
            zx(v,u);fa[rt]=u;
            csiz(rt,-1);dfs1(rt);
        }
    }
}
View Code
复制代码

 

posted @   yisiwunian  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示