Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 7669  Solved: 1894
[Submit][Status][Discuss]

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

 
题解,可持久化权值线段树上二分即可,
很好理解的,我自己写的runtime了好久,不知道为什么。
改成hzwer的就过了,GG。
 
AC代码
 
 #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 (可持久化线段树)的更多相关文章

  1. BZOJ - 2588 Spoj 10628. Count on a tree (可持久化线段树+LCA/树链剖分)

    题目链接 第一种方法,dfs序上建可持久化线段树,然后询问的时候把两点之间的所有树链扒出来做差. #include<bits/stdc++.h> using namespace std; ...

  2. 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 ...

  3. 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 ...

  4. 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 ...

  5. BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...

  6. 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个节点的树,每个点 ...

  7. 主席树 || 可持久化线段树 || 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) ...

  8. ●BZOJ 2588 Spoj 10628. Count on a tree

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2588 题解: 主席树,在线,(求LCA)感觉主席树真的好厉害...在原树上建主席树.即对于原 ...

  9. 洛谷 2633 BZOJ 2588 Spoj 10628. Count on a tree

    [题解] 蜜汁强制在线... 每个点开一个从它到根的可持久化权值线段树.查询的时候利用差分的思想在树上左右横跳就好了. #include<cstdio> #include<algor ...

随机推荐

  1. spring常用注解笔记

    spring常用注解解释: 1. Mybatis的映射文件xxxMapper.xml中resultMap标签的作用 resultMap标签是为了映射select查询出来结果的集合,其主要 作用是将实体 ...

  2. java基础(六):RabbitMQ 入门

    建议先了解为什么项目要使用 MQ 消息队列,MQ 消息队列有什么优点,如果在业务逻辑上没有此种需求,建议不要使用中间件.中间件对系统的性能做优化的同时,同时增加了系统的复杂性也维护难易度:其次,需要了 ...

  3. AJPFX总结JAVA基本数据类型

    1:关键字(掌握)        (1)被Java语言赋予特定含义的单词        (2)特点:                全部小写.        (3)注意事项:              ...

  4. [BZOJ1025][SCOI2009]游戏 DP+置换群

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1025 题目中的排数就是多少次回到原来的序列.很显然对于题目所描述的任意一种对应法则,其中一 ...

  5. oracle 代码块

    oracle 的代码块模板 declare --声明变量 begin --执行业务逻辑 exception --异常处理 end; --结束 注意:代码块每个sql语句结束都要加冒号 eg: --pl ...

  6. CAS介绍

    1.概述 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 耶 ...

  7. C# 方法 虚方法的调用浅谈 引用kdalan的博文

    我们在面试中经常碰到有关多态的问题,之前我也一直被此类问题所困扰,闹不清到底执行哪个方法. 先给出一道简单的面试题,大家猜猜看,输出是?     public class A    {         ...

  8. 【C++】模板简述(三):类模板

    上文简述了C++模板中的函数模板的格式.实例.形参.重载.特化及参数推演,本文主要介绍类模板. 一.类模板格式 类模板也是C++中模板的一种,其格式如下: template<class 形参名1 ...

  9. 洛谷 P1339 [USACO09OCT]热浪Heat Wave (堆优化dijkstra)

    题目描述 The good folks in Texas are having a heatwave this summer. Their Texas Longhorn cows make for g ...

  10. mysql 常用的语句

    1.查出当前的字段,放到一个字段中:GROUP_CONCAT(distinct b.patent_ip) ,如 (select GROUP_CONCAT(distinct b.patent_ip) f ...