zoukankan      html  css  js  c++  java
  • bzoj 2588 Count on a tree

    Description

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

    Input

    第一行两个整数N,M。
    第二行有N个整数,其中第i个整数表示点i的权值。
    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
    最后M行每行两个整数(u,v,k),表示一组询问。

    Output

    M行,表示每个询问的答案。最后一个询问不输出换行符

    Sample Input

    8 5
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    0 5 2
    10 5 3
    11 5 4
    110 8 2

    Sample Output

    2
    8
    9
    105
    7

    HINT

    HINT:

    N,M<=100000

    暴力自重。。。

    Source

    鸣谢seter

    树上的主席树,本来应该自已YY一下的但是没有想出来。。。尴尬。。。

    其实还是很简单的。。。

    每个节点以其父亲节点为历史版本建主席树,在dfs的时候insert;

    那么每个点的线段树相当于是维护了从根节点到该节点路径上的点。。。

    对于树上两点l,r路径上的第k大,那么要找出l,r的LCA,由于这个LCA也是需要被考虑的,所以还要求LCA的爸爸;

    所以每次相当于是 s[ls[l]]+s[ls[r]]-s[ls[lca]]-s[ls[fa[lca]];

    这个东西把图画出来,其实就是一个树上的前缀和思想。。。

    附上代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=100050;
      7 int gi()
      8 {
      9     int x=0,flag=1;
     10     char ch=getchar();
     11     while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
     12     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
     13     return x*flag;
     14 }
     15 int hash[N],num[N],v[N],s[N*30],sz,root[N],ls[N*30],rs[N*30];
     16 int dfn[N],head[N*2],nxt[N*2],to[N*2],son[N],dep[N],size[N],fa[N],top[N];
     17 int id[N],tt,cnt,tot,n,m,last;
     18 int find(int x)
     19 {
     20     int l=1,r=tot;
     21     while(l<=r)
     22     {
     23         int mid=(l+r)>>1;
     24         if(hash[mid]<x) l=mid+1;
     25         else r=mid-1;
     26     }
     27     return l;
     28 }
     29 void insert(int l,int r,int x,int &y,int k)
     30 {
     31     y=++sz;
     32     s[y]=s[x]+1;ls[y]=ls[x],rs[y]=rs[x];
     33     if(l==r) return;
     34     int mid=(l+r)>>1;
     35     if(k<=mid) insert(l,mid,ls[x],ls[y],k);
     36     else insert(mid+1,r,rs[x],rs[y],k);
     37 }
     38 int query(int l,int r,int a,int b,int c,int d,int k)
     39 {
     40     if(l==r) return hash[l];
     41     int mid=(l+r)>>1;
     42     if(s[ls[a]]+s[ls[b]]-s[ls[c]]-s[ls[d]]>=k)
     43         return query(l,mid,ls[a],ls[b],ls[c],ls[d],k);
     44     else return query(mid+1,r,rs[a],rs[b],rs[c],rs[d],k-(s[ls[a]]+s[ls[b]]-s[ls[c]]-s[ls[d]]));
     45 }
     46 void dfs1(int x,int f)
     47 {
     48     dep[x]=dep[f]+1;size[x]=1;
     49     insert(1,tot,root[f],root[x],find(v[x]));
     50     for(int i=head[x]; i; i=nxt[i])
     51     {
     52         int y=to[i];
     53         if(y!=f)
     54         {
     55             dfs1(y,x);
     56             fa[y]=x;size[x]+=size[y];
     57             if(size[y]>size[son[x]]) son[x]=y;
     58         }
     59     }
     60 }
     61 void dfs2(int x,int f)
     62 {
     63     dfn[x]=++tt,top[x]=f;
     64     if(son[x]) dfs2(son[x],f);
     65     for(int i=head[x]; i; i=nxt[i])
     66     {
     67         int y=to[i];
     68         if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
     69     }
     70 }
     71 int lca(int x,int y)
     72 {
     73     while(top[x]!=top[y])
     74     {
     75         if(dep[top[x]]<dep[top[y]]) swap(x,y);
     76         x=fa[top[x]];
     77     }
     78     if(dep[x]<dep[y]) swap(x,y);
     79     return y;
     80 }
     81 void lnk(int x,int y)
     82 {
     83     to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
     84     to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
     85 }
     86 int main()
     87 {
     88     n=gi(),m=gi();
     89     for(int i=1; i<=n; i++) v[i]=gi(),num[i]=v[i];
     90     sort(num+1,num+1+n);
     91     hash[++tot]=num[1];
     92     for(int i=2; i<=n; i++)
     93         if(num[i]!=num[i-1])
     94             hash[++tot]=num[i];
     95     int x,y,k;
     96     for(int i=1; i<n; i++) x=gi(),y=gi(),lnk(x,y);
     97     dfs1(1,0);dfs2(1,1);
     98     for(int i=1; i<=m; i++)
     99     {
    100         x=gi();y=gi();k=gi();x^=last;
    101         int a=root[x],b=root[y],c=root[lca(x,y)],d=root[fa[lca(x,y)]];
    102         last=query(1,tot,a,b,c,d,k);
    103         printf("%d",last);if(i!=m) printf("
    ");
    104     }
    105 }
  • 相关阅读:
    C# 根据URL获取网页截屏
    Django——WEB应用程序(手写程序),HTTP协议,BS CS架构
    jQuery——标签操作之(样式、文本内容、属性、文档处理)操作
    jQuery——简介,使用
    jQuery下载及应用
    javaScript——案例演示:点击有惊喜
    javaScript——案例演示:弹出模态框
    JavaScript——DOM操作+案例演示
    JavaScript——BOM操作
    JavaScript——杂碎小知识
  • 原文地址:https://www.cnblogs.com/qt666/p/6486584.html
Copyright © 2011-2022 走看看