您的位置:首页 > 其它

BZOJ2588: Spoj 10628. Count on a tree

2014-10-04 18:14 357 查看

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec Memory Limit: 128 MB
Submit: 1795 Solved: 371
[Submit][Status]

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

鸣谢seter

题解:
感觉很好写。
想快一点于是写了离线的tarjan 求LCA,写完了发现bzoj强制在线T_T
代码:(应该有bug,因为没评测。。。)

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 100000+1000
#define maxm 2000000+1000
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
struct edge{int go,next;}e[2*maxn];
int n,m,tot,cnt,a[maxn],id[maxn],b[maxn],head[maxn];
int sum[maxm],ls[maxm],rs[maxm],root[maxn],f[maxn][18],dep[maxn];
bool vis[maxn];
inline void insert(int x,int y)
{
e[++tot].go=y;e[tot].next=head[x];head[x]=tot;
e[++tot].go=x;e[tot].next=head[y];head[y]=tot;
}
void update(int l,int r,int x,int &y,int v)
{
y=++cnt;
sum[y]=sum[x]+1;
if(l==r)return;
ls[y]=ls[x];rs[y]=rs[x];
int mid=(l+r)>>1;
if(v<=mid)update(l,mid,ls[x],ls[y],v);else update(mid+1,r,rs[x],rs[y],v);
}
void dfs(int x)
{
for1(i,17)
if((1<<i)<=dep[x])f[x][i]=f[f[x][i-1]][i-1];else break;
for(int i=head[x],y;i;i=e[i].next)
if(!dep[y=e[i].go])
{
dep[y]=dep[x]+1;f[y][0]=x;
update(1,n,root[x],root[y],b[y]);
dfs(y);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int t=dep[x]-dep[y];
for0(i,17)
if(t&(1<<i))x=f[x][i];
if(x==y)return x;
for3(i,17,0)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
inline bool cmp(int x,int y){return a[x]<a[y];}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();m=read();
for1(i,n)a[i]=read(),id[i]=i;
sort(id+1,id+n+1,cmp);
for1(i,n)b[id[i]]=i;
for1(i,n-1)insert(read(),read());
insert(0,1);
dep[0]=1;
dfs(0);
int ans=0;
for1(i,m)
{

int x=read()^ans,y=read(),xx=lca(x,y),yy=f[xx][0],k=read(),l=1,r=n;
x=root[x];y=root[y];xx=root[xx];yy=root[yy];
while(l!=r)
{
int t=sum[ls[x]]+sum[ls[y]]-sum[ls[xx]]-sum[ls[yy]],mid=(l+r)>>1;
if(t>=k){x=ls[x];y=ls[y];xx=ls[xx];yy=ls[yy];r=mid;}
else {x=rs[x];y=rs[y];xx=rs[xx];yy=rs[yy];l=mid+1;k-=t;}
}
ans=a[id[l]];
printf("%d",ans);
if(i!=m)printf("\n");
}
return 0;
}


View Code
这貌似和dfs序没什么关系啊。。。

主席树维护的是点x到根的权值情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: