• SP11985


    这题采用离线处理的方式。

    将每个点的点权,以及每次询问的权值分别按从小到大排序。

    初始我们有一棵树,每个节点都没有点权。

    对于每次询问,将点权小于等于这次询问的权值的点添加上它原本的权值。然后判断一下询问的权值是否等于路径最大值,是则存在,不是则不存在。

    这样我们只需要用到单点修改和区间求查询,树剖维护一下即可。

    另外注意本题中 (cge 0),题目可能会询问是否存在点权为 (0) 的点,所以不要将节点初始值设为 (0)

    int n,m,tot,cnt;
    int head[maxn],ans[maxn];
    int dfn[maxn],fa[maxn],top[maxn];
    int siz[maxn],son[maxn],dep[maxn];
    struct edge{int fr,to,nxt;}e[maxn<<1];
    struct milk{
      int val,pos;
      bool operator < (const milk &b) const{
        return val<b.val;
      }
    }t[maxn];
    struct ques{
      int fr,to,c,pos;
      bool operator < (const ques &b) const{
        return c<b.c;
      }
    }q[maxn];
    
    namespace Seg{
      #define ls x<<1
      #define rs x<<1|1
      int maxx[maxn<<2];
      void cclear(){
        memset(maxx,-1,sizeof maxx);
      }
      
      void pushup(int x){
        maxx[x]=max(maxx[ls],maxx[rs]);
      }
      
      void update(int x,int l,int r,int pos,int val){
        if(l==r){
          maxx[x]=max(maxx[x],val);
          return;
        }
        int mid=l+r>>1;
        if(pos<=mid) update(ls,l,mid,pos,val);
        else update(rs,mid+1,r,pos,val);
        pushup(x);
      }
      
      int query(int x,int l,int r,int L,int R){
        if(L<=l&&R>=r) return maxx[x];
        int mid=l+r>>1,ans=-1;
        if(L<=mid) ans=max(ans,query(ls,l,mid,L,R));
        if(R>=mid+1) ans=max(ans,query(rs,mid+1,r,L,R));
        return ans;
      }
    }
    
    namespace Cut{
      void dfs1(int u,int fat){
        dep[u]=dep[fat]+1;
        siz[u]=1;fa[u]=fat;
        for(int i=head[u];i;i=e[i].nxt){
          int to=e[i].to;
          if(to==fat) continue;
          dfs1(to,u);siz[u]+=siz[to];
          if(siz[son[u]]<siz[to])son[u]=to;
        }
      }
      
      void dfs2(int u,int tp){
        top[u]=tp;dfn[u]=++cnt;
        if(son[u]) dfs2(son[u],tp);
        for(int i=head[u];i;i=e[i].nxt){
          int to=e[i].to;
          if(to==fa[u]||to==son[u]) continue;
          dfs2(to,to);
        }
      }
      
      int getmax(int x,int y){
        int ans=-1;
        while(top[x]!=top[y]){
          if(dep[top[x]]<dep[top[y]]) swap(x,y);
          ans=max(ans,Seg::query(1,1,n,dfn[top[x]],dfn[x]));
          x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        ans=max(ans,Seg::query(1,1,n,dfn[x],dfn[y]));
        return ans;
      }
    }
    
    void clear(){
      tot=0;cnt=0;Seg::cclear();
      memset(head,0,sizeof head);
      memset(son,0,sizeof son);
      memset(dfn,0,sizeof dfn);
      memset(siz,0,sizeof siz);
      memset(ans,0,sizeof ans);
    }
    
    int main(){
      while(scanf("%d%d",&n,&m)!=EOF){
        clear();
        for(int i=1;i<=n;i++) 
          t[i].val=read(),t[i].pos=i;
        for(int i=1,fr,to;i<n;i++){
          fr=read();to=read();
          add(fr,to);add(to,fr);
        }
        Cut::dfs1(1,0);Cut::dfs2(1,1);
        for(int i=1;i<=m;i++)
          q[i].fr=read(),q[i].to=read(),
          q[i].c=read(),q[i].pos=i;
        sort(t+1,t+n+1);sort(q+1,q+m+1);int Now=1;
        for(int i=1;i<=m;i++){
          while(Now<=n&&t[Now].val<=q[i].c){
            Seg::update(1,1,n,dfn[t[Now].pos],t[Now].val);
            Now++;
          }
          ans[q[i].pos]=(Cut::getmax(q[i].fr,q[i].to)==q[i].c);
        }
        for(int i=1;i<=m;i++) printf(ans[i]?"Find
    ":"NotFind
    ");
      }
      return 0;
    }
    
  • 相关阅读:
    设计模式----单例模式
    C++ 派生类
    C++ 操作符
    构造,清理,拷贝和移动
    php的yii框架开发总结10
    php的yii框架开发总结9
    php的yii框架开发总结8
    php的yii框架开发总结7
    php的yii框架开发总结6
    php的yii框架开发总结5
  • 原文地址:https://www.cnblogs.com/KnightL/p/15480944.html
Copyright © 2020-2023  润新知