BZOJ 2588 Count on a tree (COT) 是持久的段树
标题效果:两棵树之间的首次查询k大点的权利。
思维:树木覆盖树,事实上,它是正常的树木覆盖了持久段树。
由于使用权值段树可以寻求区间k大,然后应用到持久段树思想,间隔可以做减法。详见代码。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define NIL (tree[0])
using namespace std; pair<int,int> src[MAX]; struct Complex{
Complex *son[2];
int cnt; Complex(Complex *_,Complex *__,int ___):cnt(___) {
son[0] = _;
son[1] = __;
}
Complex() {}
}*tree[MAX]; int points,asks;
int xx[MAX]; int head[MAX],total;
int next[MAX << 1],aim[MAX << 1]; int father[MAX][20],deep[MAX]; inline void Add(int x,int y);
void DFS(int x);
void SparseTable(); Complex *BuildTree(Complex *pos,int x,int y,int val);
int GetAns(Complex *l,Complex *r,Complex *f,Complex *p,int x,int y,int k);
int GetLCA(int x,int y);
int Ask(int x,int y,int k); int main()
{
cin >> points >> asks;
for(int i = 1;i <= points; ++i)
scanf("%d",&src[i].first),src[i].second = i;
sort(src + 1,src + points + 1);
for(int i = 1;i <= points; ++i)
xx[src[i].second] = i;
for(int x,y,i = 1;i < points; ++i) {
scanf("%d%d",&x,&y);
Add(x,y),Add(y,x);
}
NIL = new Complex(NULL,NULL,0);
NIL->son[0] = NIL->son[1] = NIL;
DFS(1);
SparseTable();
int now = 0;
for(int x,y,k,i = 1;i <= asks; ++i) {
scanf("%d%d%d",&x,&y,&k);
printf("%d",now = src[Ask(x ^ now,y,k)].first);
if(i != asks) puts("");
}
return 0;
} inline void Add(int x,int y)
{
next[++total] = head[x];
aim[total] = y;
head[x] = total;
} void DFS(int x)
{
deep[x] = deep[father[x][0]] + 1;
tree[x] = BuildTree(tree[father[x][0]],1,points,xx[x]);
for(int i = head[x];i;i = next[i]) {
if(aim[i] == father[x][0]) continue;
father[aim[i]][0] = x;
DFS(aim[i]);
}
} void SparseTable()
{
for(int j = 1;j <= 19; ++j)
for(int i = 1;i <= points; ++i)
father[i][j] = father[father[i][j - 1]][j - 1];
} int Ask(int x,int y,int k)
{
int lca = GetLCA(x,y);
return GetAns(tree[x],tree[y],tree[lca],tree[father[lca][0]],1,points,k);
} Complex *BuildTree(Complex *pos,int x,int y,int val)
{
int mid = (x + y) >> 1;
if(x == y) return new Complex(NIL,NIL,pos->cnt + 1);
if(val <= mid) return new Complex(BuildTree(pos->son[0],x,mid,val),pos->son[1],pos->cnt + 1);
return new Complex(pos->son[0],BuildTree(pos->son[1],mid + 1,y,val),pos->cnt + 1);
} int GetLCA(int x,int y)
{
if(deep[x] < deep[y]) swap(x,y);
for(int i = 19; ~i; --i)
if(deep[father[x][i]] >= deep[y])
x = father[x][i];
if(x == y) return x;
for(int i = 19; ~i; --i)
if(father[x][i] != father[y][i])
x = father[x][i],y = father[y][i];
return father[x][0];
} int GetAns(Complex *l,Complex *r,Complex *f,Complex *p,int x,int y,int k)
{
if(x == y) return x;
int mid = (x + y) >> 1;
int temp = l->son[0]->cnt + r->son[0]->cnt - f->son[0]->cnt - p->son[0]->cnt;
if(k <= temp) return GetAns(l->son[0],r->son[0],f->son[0],p->son[0],x,mid,k);
return GetAns(l->son[1],r->son[1],f->son[1],p->son[1],mid + 1,y,k - temp);
}
版权声明:本文博客原创文章。博客,未经同意,不得转载。
BZOJ 2588 Count on a tree (COT) 是持久的段树的更多相关文章
- bzoj 2588 Count on a tree 解题报告
Count on a tree 题目描述 给定一棵\(N\)个节点的树,每个点有一个权值,对于\(M\)个询问\((u,v,k)\),你需要回答\(u\) \(xor\) \(lastans\)和\( ...
- BZOJ.2588.Count on a tree(主席树 静态树上第k小)
题目链接 /* 序列上的主席树 某点是利用前一个点的根建树 同理 树上的主席树 某个节点可以利用其父节点(is unique)的根建树 排名可以利用树上前缀和求得: 对于(u,v),w=LCA(u,v ...
- bzoj 2588 Count on a tree
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- SPOJ 10628 COT - Count on a tree(在树上建立主席树)(LCA)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
- SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
- 2588: Count on a tree
敢问和zwt的树有何区别..改了读入直接交..四百个人A,三百多个PE..于是果断贡献几发PE.. http://ideone.com/9XCg3D
- 【BZOJ】【2588】COT(Count On a Tree)
可持久化线段树 maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树. 然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 19 ...
- 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 ...
- BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树
2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...
随机推荐
- Android FragmentStatePageAdapter的使用Demo
上一篇写过FragmentPagerAdapter,这篇来介绍FragmentStatePagerAdapter,那么两者之间有何差别呢: FragmentPagerAdapter很多其它的用于少量界 ...
- 基于HttpClient 4.3的可訪问自签名HTTPS网站的新版工具类
本文出处:http://blog.csdn.net/chaijunkun/article/details/40145685,转载请注明.因为本人不定期会整理相关博文,会对相应内容作出完好.因此强烈建议 ...
- zoj 3822 Domination(2014牡丹江区域赛D称号)
Domination Time Limit: 8 Seconds Memory Limit: 131072 KB Special Judge Edward is the headm ...
- python关于for循环的几个函数
1.enumerate:返回2个值,1是当前的for循环的第几轮,2是循环得到的数值 enumerate works by supplying a corresponding index to eac ...
- jQuery的理论基础
概述 jQuery是用JavaScript语言编写的函数库,我们用时,可以直接调用jQuery中相应的函数,对于JavaScript的理解,前面的博客已经介绍过了,在这里只说一下函数的作用,也可以说为 ...
- PHP_保留两位小数而且四舍五入_保留两位小数而且不四舍五入
php保留两位小数而且四舍五入 $num = 123213.666666; echo sprintf("%.2f", $num); php保留两位小数而且不四舍五入 $num = ...
- 使用Socket沟通
当两台电脑TCP/IP协议进行通讯.平时Socket对象来表示该通信接口的两端,并通过Socket生产I/O流进行网络通信. 其中ServerSocket对象可以接收从连接的其他通信实体的请求.这个目 ...
- 转载:PHP时间戳 strtotime()使用方法和技巧
在php中我想要获取时间戳有多种方法,最常用的就是使用time函数与strtotime()函数把日期转换成时间戳了 获取指定的年月日转化为时间戳:pHP时间戳函数获取指定日期的unix时间戳 strt ...
- [文学阅读] METEOR: An Automatic Metric for MT Evaluation with Improved Correlation with Human Judgments
METEOR: An Automatic Metric for MT Evaluation with Improved Correlation with Human Judgments Satanje ...
- android下获取无线wif信号、ssid、MAC等操作类
一个android下获取无线wif信号.ssid.MAC等操作的类. WifiAdmin.java package com.afu; import java.util.List; import and ...