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
暴力自重。。。
 
思路:
  主席树;
  树上一段路径中主席树的状态可以用root[from]+root[to]-root[lca]-root[f[lca]]来表示
  但是,这个题和spoj上不太一样
  要用到long long
  而且每次的from都是一个二进制数,需要xor上一次查询的答案;
 
来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define LL long long
#define maxn 100001 using namespace std; struct TreeNodeType {
LL dis,lc,rc;
};
struct TreeNodeType tree[maxn*]; struct EdgeType {
LL to,next;
};
struct EdgeType edge[maxn<<]; LL if_z,n,m,hash[maxn],hash_[maxn],cnt,head[maxn];
LL size_,tot,root[maxn],deep[maxn],f[maxn],size[maxn];
LL belong[maxn]; char Cget; inline void read_int(LL &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(LL from,LL to)
{
cnt++;
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt;
} void tree_build(LL now,LL l,LL r)
{
tree[now].dis=;
if(l==r) return ;
LL mid=(l+r)>>;
tree[now].lc=++tot;
tree_build(tot,l,mid);
tree[now].rc=++tot;
tree_build(tot,mid+,r);
} void tree_add(LL pre,LL now,LL to,LL l,LL r)
{
tree[now].dis=tree[pre].dis+;
if(l==r) return ;
LL mid=(l+r)>>;
if(to>mid)
{
tree[now].lc=tree[pre].lc;
tree[now].rc=++tot;
tree_add(tree[pre].rc,tree[now].rc,to,mid+,r);
}
else
{
tree[now].rc=tree[pre].rc;
tree[now].lc=++tot;
tree_add(tree[pre].lc,tree[now].lc,to,l,mid);
}
} void search(LL now,LL pre)
{
LL pos=cnt++;
f[now]=pre;
deep[now]=deep[pre]+;
hash_[now]=lower_bound(hash+,hash+size_+,hash_[now])-hash;
root[now]=++tot;
tree_add(root[pre],root[now],hash_[now],,size_);
for(LL i=head[now];i;i=edge[i].next)
{
if(edge[i].to==pre) continue;
search(edge[i].to,now);
}
size[now]=cnt-pos;
} void search_(LL now,LL chain)
{
LL pos=;
belong[now]=chain;
for(LL i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]) continue;
if(size[edge[i].to]>size[pos]) pos=edge[i].to;
}
if(pos==) return ;
search_(pos,chain);
for(LL i=head[now];i;i=edge[i].next)
{
if(pos==edge[i].to||edge[i].to==f[now]) continue;
search_(edge[i].to,edge[i].to);
}
} inline LL tree_lca(LL x,LL y)
{
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
x=f[belong[x]];
}
if(deep[x]<deep[y]) return x;
else return y;
} inline LL tree_query(LL x,LL y,LL lca,LL flca,LL l,LL r,LL k)
{
LL dis,mid;
while(l!=r)
{
dis=tree[tree[x].lc].dis+tree[tree[y].lc].dis-tree[tree[lca].lc].dis-tree[tree[flca].lc].dis;
mid=(l+r)>>;
if(k>dis)
{
k-=dis;
l=mid+;
lca=tree[lca].rc;
flca=tree[flca].rc;
x=tree[x].rc,y=tree[y].rc;
}
else
{
r=mid;
lca=tree[lca].lc;
flca=tree[flca].lc;
x=tree[x].lc,y=tree[y].lc;
}
}
return l;
} int main()
{
read_int(n),read_int(m);
for(LL i=;i<=n;i++)
{
read_int(hash[i]);
hash_[i]=hash[i];
}
LL from,to;
for(LL i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
edge_add(to,from);
}
sort(hash+,hash+n+);
size_=unique(hash+,hash+n+)-hash-;
root[]=++tot;
tree_build(root[],,size_);
cnt=,search(,);
cnt=,search_(,);
LL K,last=;
for(LL i=;i<=m;i++)
{
read_int(from),read_int(to),read_int(K);
from=from^last;
LL lca=tree_lca(from,to);
last=hash[tree_query(root[from],root[to],root[lca],root[f[lca]],,size_,K)];
if(i!=m) printf("%lld\n",last);
else printf("%lld",last);
}
return ;
}

AC日记——Count on a tree bzoj 2588的更多相关文章

  1. AC日记——Count on a tree II spoj

    Count on a tree II 思路: 树上莫队: 先分块,然后,就好办了: 来,上代码: #include <cmath> #include <cstdio> #inc ...

  2. AC日记——算术天才⑨与等差数列 bzoj 4373

    4373 思路: 判断一个数列是否是等差数列: 1,最大值减去最小值==(区间个数-1)*k: 2,gcd==k: 3,不能有重复(不会这判断这一条,但是数据水就过了): 来,上代码: #includ ...

  3. AC日记——[HNOI2008]玩具装箱toy bzoj 1010

    1010 思路: 斜率优化DP: 跪烂大佬 代码: #include <bits/stdc++.h> using namespace std; #define maxn 50005 #de ...

  4. AC日记——[Sdoi2008]Cave 洞穴勘测 bzoj 2049

    2049 思路: lct模板: 代码: #include <cstdio> #include <cstring> #include <iostream> #incl ...

  5. AC日记——[HNOI2012]永无乡 bzoj 2733

    2733 思路: 启发式合并splay(n*log^2n): 来,上代码: #include <cstdio> #include <cstring> #include < ...

  6. AC日记——[HNOI2008]水平可见直线 bzoj 1007

    1007 思路: 维护一个下凸壳: 用单调栈来维护这玩意儿: 先将斜率排序: 然后判断栈顶元素和当前元素的交点x是否小于栈顶元素和栈顶上一个元素的交点x: 注意: 人神共愤的精度问题和输出空格问题: ...

  7. AC日记——小M的作物 bzoj 3438

    3438 思路: 最小割(完全不懂看的题解): s向每个作物连边,s-x ai,x-t bi: 然后s向作物集合连边,cia: 作物集合拆点向t连边,cib: 作物集合第一个点向作物连边INF: 作物 ...

  8. 【BZOJ】【2588】COT(Count On a Tree)

    可持久化线段树 maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树. 然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 19 ...

  9. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

随机推荐

  1. ubuntu16.04安装 java JDK8

    安装openjdk1.更新软件包列表: sudo apt-get update 2.安装openjdk-8-jdk: sudo apt-get install openjdk-8-jdk 3.查看ja ...

  2. NoSQL 数据库之MongoDB

    1.MongoDB简介 1.1什么是MongoDB MongoDB 是一个跨平台的,面向文档的数据库,是当前 NoSQL 数据库产品中最热门的一种.它介于关系数据库和非关系数据库之间,是非关系数据库当 ...

  3. Python基础-函数参数

    Python基础-函数参数 写在前面 如非特别说明,下文均基于Python3 摘要 本文详细介绍了函数的各种形参类型,包括位置参数,默认参数值,关键字参数,任意参数列表,强制关键字参数:也介绍了调用函 ...

  4. (转).gitignore详解

    本文转自http://sentsin.com/web/666.html 今天讲讲Git中非常重要的一个文件——.gitignore. 首先要强调一点,这个文件的完整文件名就是“.gitignore”, ...

  5. LeetCode(242)Valid Anagram

    题目 Given two strings s and t, write a function to determine if t is an anagram of s. For example, s ...

  6. phpMyAdmin关于PHP 5.5+ is required. Currently installed version is: 5.4.16问题

    出现这个提示PHP 5.5+ is required. Currently installed version is: 5.4.16原因可能是: phpmyadmin 版本太新,最小需要php5.5. ...

  7. Flask-用户角色及权限

    app/models.py class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=T ...

  8. Django之include本质

    一. URL name详解 from django.conf.urls import url from django.contrib import admin from calc import vie ...

  9. loj2024「JLOI / SHOI2016」侦查守卫

    too hard #include <iostream> #include <cstdio> using namespace std; int n, d, m, uu, vv, ...

  10. Leetcode31--->Next Permutation(数字的下一个排列)

    题目: 给定一个整数,存放在数组中,求出该整数的下一个排列(字典顺序):要求原地置换,且不能分配额外的内存 举例: 1,2,3 → 1,3,2:  3,2,1 → 1,2,3:  1,1,5 → 1, ...