bzoj 2588 Spoj 10628. Count on a tree (可持久化线段树)
Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MB
Submit: 7669 Solved: 1894
[Submit][Status][Discuss]
Description
Input
Output
M行,表示每个询问的答案。最后一个询问不输出换行符
Sample Input
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
8
9
105
7
HINT
Source
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define N 100007
#define M 2000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,top,sz,ind;
int a[N],zhi[N];
int num[N],fx[N];
int cnt,head[N],next[*N],rea[*N];
int ls[M],rs[M],sum[M],root[N];
int deep[N],fa[N][]; int find(int x)
{
int l=,r=top;
while(l<=r)
{
int mid=(l+r)>>;
if (zhi[mid]==x) return mid;
if (zhi[mid]<x) l=mid+;
else r=mid-;
}
}
void add(int u,int v)
{
next[++cnt]=head[u];
head[u]=cnt;
rea[cnt]=v;
}
void dfs(int u)
{
ind++,num[ind]=u,fx[u]=ind;
for (int i=;i<=;i++)
fa[u][i]=fa[fa[u][i-]][i-];
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (fa[u][]!=v)
{
deep[v]=deep[u]+;
fa[v][]=u;
dfs(v);
}
}
}
int lca(int a,int b)
{
if (deep[a]<deep[b]) swap(a,b);
int i;
for (i=;(<<i)<=deep[a];i++);
i--;
for (int j=i;j>=;j--)
if (deep[a]-(<<j)>=deep[b]) a=fa[a][j];
if (a==b) return a;
for (int j=i;j>=;j--)
if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j];
return fa[a][];
}
void change(int l,int r,int x,int &y,int z)
{
y=++sz;
sum[y]=sum[x]+;
if (l==r) return;
ls[y]=ls[x],rs[y]=rs[x];
int mid=(l+r)>>;
if (z<=mid) change(l,mid,ls[x],ls[y],z);
else change(mid+,r,rs[x],rs[y],z);
}
int query(int l,int r,int a,int b,int c,int d,int rank)
{
if (l==r) return zhi[l];
int mid=(l+r)>>,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
if (tmp>=rank) return query(l,mid,ls[a],ls[b],ls[c],ls[d],rank);
else return query(mid+,r,rs[a],rs[b],rs[c],rs[d],rank-tmp); }
int que(int x,int y,int rk)
{
int a=x,b=y,c=lca(x,y),d=fa[c][];
a=root[fx[a]],b=root[fx[b]],c=root[fx[c]],d=root[fx[d]];
int l=,r=top;
while(l<r)
{
int mid=(l+r)>>;
int tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
if(tmp>=rk)r=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d];
else rk-=tmp,l=mid+,a=rs[a],b=rs[b],c=rs[c],d=rs[d];
}
return zhi[l];
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for (int i=;i<=n;i++)
a[i]=read(),zhi[i]=a[i];
sort(zhi+,zhi+n+);
top=;
for (int i=;i<=n;i++)
if (zhi[i]!=zhi[i-]) zhi[++top]=zhi[i];
for (int i=;i<=n;i++)
a[i]=find(a[i]);
for (int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y),add(y,x);
}
dfs();
for (int i=;i<=n;i++)
{
int t=num[i];//从标号的1开始。
change(,top,root[fx[fa[t][]]],root[i],a[t]);
}
int last=;
for(int i=;i<=m;i++)
{
int x=read(),y=read(),rk=read();
x^=last;
last=que(x,y,rk);
printf("%d",last);
if(i!=m)printf("\n");
}
/*for (int i=1;i<=m;i++)
{
int x=read(),y=read(),rank=read();
x^=last;
int a=root[fx[x]],b=root[fx[y]],c=root[fx[lca(x,y)]],d=root[fx[fa[lca(x,y)][0]]];
last=query(1,top,a,b,c,d,rank);
printf("%d",last);
if (i!=m) cout<<endl;
}*/
}
Wrong代码
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define N 100007
#define M 3000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,top,sz,ind;
int a[N],zhi[N];
int num[N],fx[N];
int cnt,head[N],next[*N],rea[*N];
int ls[M],rs[M],sum[M],root[N];
int deep[N],fa[N][]; int find(int x)
{
int l=,r=top;
while(l<=r)
{
int mid=(l+r)>>;
if (zhi[mid]==x) return mid;
if (zhi[mid]<x) l=mid+;
else r=mid-;
}
}
void add(int u,int v)
{
next[++cnt]=head[u];
head[u]=cnt;
rea[cnt]=v;
}
void dfs(int u)
{
ind++,num[ind]=u,fx[u]=ind;
for (int i=;i<=;i++)
fa[u][i]=fa[fa[u][i-]][i-];
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (fa[u][]!=v)
{
deep[v]=deep[u]+;
fa[v][]=u;
dfs(v);
}
}
}
int lca(int a,int b)
{
if (deep[a]<deep[b]) swap(a,b);
int i;
for (i=;(<<i)<=deep[a];i++);
i--;
for (int j=i;j>=;j--)
if (deep[a]-(<<j)>=deep[b]) a=fa[a][j];
if (a==b) return a;
for (int j=i;j>=;j--)
if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j];
return fa[a][];
}
void change(int l,int r,int x,int &y,int z)
{
y=++sz;
sum[y]=sum[x]+;
if (l==r) return;
ls[y]=ls[x],rs[y]=rs[x];
int mid=(l+r)>>;
if (z<=mid) change(l,mid,ls[x],ls[y],z);
else change(mid+,r,rs[x],rs[y],z);
}
int query(int l,int r,int a,int b,int c,int d,int rank)
{
if (l==r) return zhi[l];
int mid=(l+r)>>,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
if (tmp>=rank) return query(l,mid,ls[a],ls[b],ls[c],ls[d],rank);
else return query(mid+,r,rs[a],rs[b],rs[c],rs[d],rank-tmp);
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for (int i=;i<=n;i++)
a[i]=read(),zhi[i]=a[i];
sort(zhi+,zhi+n+);
top=;
for (int i=;i<=n;i++)
if (zhi[i]!=zhi[i-]) zhi[++top]=zhi[i];
for (int i=;i<=n;i++)
a[i]=find(a[i]);
for (int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y),add(y,x);
}
dfs();
for (int i=;i<=n;i++)
{
int t=num[i];//从标号的1开始。
change(,top,root[fx[fa[t][]]],root[i],a[t]);
}
int last=;
for (int i=;i<=m;i++)
{
int x=read(),y=read(),rank=read();
x^=last;
int a=root[fx[x]],b=root[fx[y]],c=root[fx[lca(x,y)]],d=root[fx[fa[lca(x,y)][]]];
last=query(,top,a,b,c,d,rank);
printf("%d",last);
if (i!=m) cout<<endl;
}
}
bzoj 2588 Spoj 10628. Count on a tree (可持久化线段树)的更多相关文章
- BZOJ - 2588 Spoj 10628. Count on a tree (可持久化线段树+LCA/树链剖分)
题目链接 第一种方法,dfs序上建可持久化线段树,然后询问的时候把两点之间的所有树链扒出来做差. #include<bits/stdc++.h> using namespace std; ...
- 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 ...
- 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 主席树,离散化,可持久,倍增LCA
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588 2588: Spoj 10628. Count on a tree Time Limit ...
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...
- 主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree
题面: Count on a tree 题解: 主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y) ...
- ●BZOJ 2588 Spoj 10628. Count on a tree
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2588 题解: 主席树,在线,(求LCA)感觉主席树真的好厉害...在原树上建主席树.即对于原 ...
- 洛谷 2633 BZOJ 2588 Spoj 10628. Count on a tree
[题解] 蜜汁强制在线... 每个点开一个从它到根的可持久化权值线段树.查询的时候利用差分的思想在树上左右横跳就好了. #include<cstdio> #include<algor ...
随机推荐
- ORA-00445: Background Process "xxxx" Did Not Start After 120 Seconds
Recent linux kernels have a feature called Address Space Layout Randomization (ASLR).ASLR is a feat ...
- js点击修改按钮后修改
<button id="click">改变内容</button> <div id="t">要改变的内容</div> ...
- 外文翻译 《How we decide》赛场上的四分卫 第四节
这是第一章的最后一节. 书的导言 本章第一节 本章第二节 本章第三节 制作肥皂剧是非常不易的.整个制作组都要很紧张的工作,每天都要拍摄一些新的事件.新的大转折的剧情需要被想象出来,新的剧本需要被编写, ...
- Android BitmapFactory.decodeFile(filePath, options) 返回 Null 6.0权限
今天在做拍照上传的时候遇到个问题,根据路径获取Bitmap 失败,一直返回空,以为这个路径获取Bitmap代码久经考验,不怀疑它,找参数传入是否正确,初步怀疑是 filePath 没传进去,打印 fi ...
- MVC中使用MVCPager简单分页
一.建立数据库以及建立MVC项目 自己随便建立一个数据库,并且添加数据.我建立的数据库如下. 二.建立LINQ to SQL映射. 然后一步步点确定 三.编写代码 在Controllers中建立控制器 ...
- 支付宝SDK
由于支付宝SDK对于整个支付流程已经介绍的十分详细了,在这里我就简单说一些注意点. 由于存在支付宝可能没有安装的情况,所以我们在调用支付宝支付时,需要对其进行判断,做出不同的处理方式,即是使用客户端支 ...
- Android SDK镜像更新网速慢的解决问题
通过更换代理解决 Android SDK 在线更新镜像服务器资源:大连东软信息学院镜像服务器地址:http://mirrors.neusoft.edu.cn 端口:80北京化工大学镜像服务器地址:IP ...
- 移动端展示pdf(在线打开pdf)
需求:在手机微信浏览器或者其他浏览器中打开pdf 准备:前端插件:查找pdf.js 官网地址:http://mozilla.github.io/pdf.js/ 在官网中下载demo 注释:pdf的d ...
- ajax跨域上传图片
前台页面 var data = new FormData(); data.append('file', file); data.append('app', 'goods'); $.ajax({ url ...
- apache反向代理配置
apache简单的反向代理配置 Proxypass /api /http://locahost:3000 反向代理-1.jpg