一开始一看树上的操作,就无脑写了树链剖分+主席树

然后果断T了,因为树链剖分+主席树必然带来两个log的复杂度

而且树链剖分复杂度还比较大……

后来发现其实没必要,在这道题,我们可以直接利用主席树维护

只不过,每个点维护的是它到它的祖先上数值出现的个数

则u,v之间各个数值出现的数值=tree[u]+tree[v]-tree[lca(u,v)]-tree[fa[lca(u,v)]];

这是一个满足区间减法的问题所以可以这么做

总结一下,在静态树上(相对于动态树而言,没有改变树的形态)

  1. 如果问题满足区间减法性质,如求k大,那就直接做,或者用dfs序(下篇再写)

  2. 如果不满足,那就要套树链剖分了

 const maxn=;
type node=record
       po,next:longint;
     end;
     point=record
       l,r,s:longint;
     end; var tree:array[..maxn*] of point;
    w:array[..*maxn] of node;
    h,p,c,b,a,q1,q2,rank,sa,fa,d:array[..maxn] of longint;
    anc:array[..maxn,..] of longint;
    j,t,z,e,i,n,m,k,x,y,len,ans,s:longint; procedure swap(var a,b:longint);
  var c:longint;
  begin
    c:=a;
    a:=b;
    b:=c;
  end; procedure update(i:longint);
  begin
    tree[i].s:=tree[tree[i].l].s+tree[tree[i].r].s;
  end; procedure add(x,y:longint);
  begin
    inc(len);
    w[len].po:=y;
    w[len].next:=p[x];
    p[x]:=len;
  end; procedure sort(l,r: longint);
  var i,j,x:longint;
  begin
    i:=l;
    j:=r;
    x:=a[(l+r) div ];
    repeat
      while (a[i]<x) do inc(i);
      while (x<a[j]) do dec(j);
      if not(i>j) then
      begin
        swap(a[i],a[j]);
        swap(c[i],c[j]);
        inc(i);
        j:=j-;
      end;
    until i>j;
    if l<j then sort(l,j);
    if i<r then sort(i,r);
  end; function build(l,r:longint):longint;
  var q,m:longint;
  begin
    inc(t);
    if l=r then exit(t)
    else begin
      q:=t;
      m:=(l+r) shr ;
      tree[q].l:=build(l,m);
      tree[q].r:=build(m+,r);
      exit(q);
    end;
  end; function add(last,l,r,x:longint):longint;
  var q,m:longint;
  begin
    inc(t);
    if l=r then
    begin
      tree[t].s:=tree[last].s+;
      exit(t);
    end
    else begin
      q:=t;
      m:=(l+r) shr ;
      if x<=m then
      begin
        tree[q].r:=tree[last].r;
        last:=tree[last].l;
        tree[q].l:=add(last,l,m,x);
      end
      else begin
        tree[q].l:=tree[last].l;
        last:=tree[last].r;
        tree[q].r:=add(last,m+,r,x);
      end;
      update(q);
      exit(q);
    end;
  end; function getans(l,r,k:longint):longint;
  var i,m,s1:longint;
  begin
    if l=r then
      exit(sa[l])
    else begin
      m:=(l+r) shr ;
      s1:=tree[tree[x].l].s+tree[tree[y].l].s-tree[tree[z].l].s-tree[tree[e].l].s;
      if s1>=k then
      begin
        x:=tree[x].l;
        y:=tree[y].l;
        z:=tree[z].l;
        e:=tree[e].l;
        exit(getans(l,m,k));
      end
      else begin
        x:=tree[x].r;
        y:=tree[y].r;
        z:=tree[z].r;
        e:=tree[e].r;
        k:=k-s1;
        exit(getans(m+,r,k));
      end;
    end;
  end; function lca(x,y:longint):longint;
  var i,p:longint;
  begin
    if d[x]<d[y] then swap(x,y);
    if x=y then exit(x);
    p:=trunc(ln(d[x])/ln());
    for i:=p downto do
      if d[x]- shl i>=d[y] then x:=anc[x,i];
    if x=y then exit(x);
    for i:=p downto do
      if (anc[x,i]<>anc[y,i]) and (anc[x,i]<>) then
      begin
        x:=anc[x,i];
        y:=anc[y,i];
      end;
    exit(fa[x]);
  end; procedure dfs(x:longint);
  var i,y:longint;
  begin
    h[x]:=add(h[fa[x]],,s,rank[x]);
    i:=p[x];
    while i<> do
    begin
      y:=w[i].po;
      if fa[x]<>y then
      begin
        d[y]:=d[x]+;
        fa[y]:=x;
        dfs(y);
      end;
      i:=w[i].next;
    end;
  end; begin
  readln(n,m);
  for i:= to n do
  begin
    read(a[i]);
    c[i]:=i;
  end;
  sort(,n);
  s:=;
  sa[]:=a[];
  rank[c[]]:=;
  for i:= to n do
  begin
    if a[i]<>a[i-] then
    begin
      inc(s);
      sa[s]:=a[i];
    end;
    rank[c[i]]:=s;
  end;
  for i:= to n- do
  begin
    readln(x,y);
    add(x,y);
    add(y,x);
  end;
  h[]:=build(,s);
  dfs();   for i:= to n do
    anc[i,]:=fa[i];
  k:=trunc(ln(n)/ln());
  for j:= to k do
    for i:= to n do
    begin
      x:=anc[i,j-];
      if x<> then anc[i,j]:=anc[x,j-];
    end;   ans:=;
  for i:= to m do
  begin
    readln(x,y,k);
    x:=x xor ans;
    z:=lca(x,y);
    e:=h[fa[z]];
    z:=h[z];
    x:=h[x];
    y:=h[y];
    ans:=getans(,s,k);
    write(ans);
    if i<>m then writeln;
  end;
end.

bzoj2588的更多相关文章

  1. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  2. 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA

    [BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...

  3. 【bzoj2588】Count on a tree

    Portal -->bzoj2588 Solution 不行我一定要来挂这道题qwq很气愤qwq(其实还不是因为自己蠢..) 额首先说一下正解 如果这个问题放在序列上面的话..直接离散化一下然后 ...

  4. 洛谷P2633/bzoj2588 Count on a tree (主席树)

    洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...

  5. BZOJ2588 SPOJ10628 Count on a tree 【主席树】

    BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ...

  6. [bzoj2588][Spoj10628]Count on a tree_主席树

    Count on a tree bzoj-2588 Spoj-10628 题目大意:给定一棵n个点的树,m次查询.查询路径上k小值. 注释:$1\le n,m\le 10^5$. 想法:好像更博顺序有 ...

  7. [bzoj2588][count on a tree] (主席树+lca)

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

  8. BZOJ2588: Spoj 10628. Count on a tree

    传送门 刚开始看错题以为是dfs序瞎搞.. 后来看清题了开始想用树剖瞎搞... 感觉要滚粗啊.. 对于每个点到根的路径建立线段树,暴力建MLE没跑,上主席树,然后$(x,y)$的路径就可以先求出来$L ...

  9. 【填坑向】spoj COT/bzoj2588 Count on a tree

    这题是学主席树的时候就想写的,,, 但是当时没写(懒) 现在来填坑 = =日常调半天lca(考虑以后背板) 主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分 ...

  10. bzoj2588 Count on a tree

    题意:给定一棵树,有点权,不带修改,询问路径点权第K大,强制在线. 这道题建主席树的方法好机智.按照BFS/DFS序建树,对于每个点,建出"这个点到根节点的路径上的点"组成的权值线 ...

随机推荐

  1. 第二篇:从 GPU 的角度理解并行计算

    前言 本文从使用 GPU 编程技术的角度来了解计算中并行实现的方法思路. 并行计算中需要考虑的三个重要问题 1. 同步问题 在操作系统原理的相关课程中我们学习过进程间的死锁问题,以及由于资源共享带来的 ...

  2. Android进阶笔记03:Android应用中实现查看"附近的人"的功能

    1. 要实现" 附近的人" 这功能,然后就研究了下: (1)首先要做的就是要获取到自己当前位置的经纬度(编程获取手机GPS定位模块的信息,进而获取自己当前位置的经纬度) (2)然后 ...

  3. Java 原始数据类型转换

    在开发中经常遇到数据类型转换的问题,大多数都是拿来强制转换,强制转换可能会出现你意想不到的问题: int a = -1; 我们经过多重转换之后:int b = (int)(char)(byte) a ...

  4. Android中全局搜索(QuickSearchBox)详解

    http://blog.csdn.net/mayingcai1987/article/details/6268732 1. 标题: 应用程序如何全面支持搜索 2. 引言: 如果想让某个应用程序支持全局 ...

  5. ArrayList 类和List<T>泛型类

    ArrayList集合类在System.Colletions命名空间下,它其实是一个特殊的数组,它可以动态的添加和删除元素,根据元素的改变自动决定它自身的大小,也可以灵活的插入元素等操作,使用起来要比 ...

  6. Topas命令详解

    Topas命令详解 执行topas命令后如图所示: #topas 操作系统的最全面动态,而又查看方便的性能视图就是topas命令了,下面以topas输出为例,对AIX系统的性能监控做简要描述,供运维工 ...

  7. 九、C# 合式类型

    本章要描述如何最终完善类型声明.   1.重写Ojbect中的成员   重写ToString() 默认情况下,在任何对象上调用 ToString()会返回类的完全限定名称,所以有时候需要重载这个函数, ...

  8. X-Plane飞行模拟器购买安装

    要玩起X-Plane第一个步骤当然是购买了,要购买其实非常简单,只需要一张能够支持MasterCard或者其他外币结算的信用卡,在http://www.x-plane.com/官网上购买即可,比逛淘宝 ...

  9. Problem 1108 - 淼·诺贝尔

    #include<iostream> #include<vector> #include<algorithm> using namespace std; struc ...

  10. mongo db安装和php,python插件安装

    安装mongodb 1.下载,解压mongodb(下载解压目录为/opt) 在/opt目录下执行命令 wget fastdl.mongodb.org/linux/mongodb-linux-x86_6 ...