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

题解:
感觉很好写。
想快一点于是写了离线的tarjan 求LCA,写完了发现bzoj强制在线T_T
代码:(应该有bug,因为没评测。。。)
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<string>
12 #define inf 1000000000
13 #define maxn 500+100
14 #define maxm 500+100
15 #define eps 1e-10
16 #define ll long long
17 #define pa pair<int,int>
18 #define for0(i,n) for(int i=0;i<=(n);i++)
19 #define for1(i,n) for(int i=1;i<=(n);i++)
20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
22 #define mod 1000000007
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 struct edge{int go,next;}e[2*maxn];
32 int n,m,tot,cnt,u[maxn],v[maxn],rk[maxn],a[maxn],id[maxn],b[maxn],fa[maxn],head[maxn];
33 int sum[maxm],ls[maxm],rs[maxm],lca[maxn],root[maxn];
34 vector<pa>q[maxn];
35 bool vis[maxn];
36 inline void insert(int x,int y)
37 {
38     e[++tot].go=y;e[tot].next=head[x];head[x]=tot;
39     e[++tot].go=x;e[tot].next=head[y];head[y]=tot;
40 }
41 void update(int l,int r,int x,int &y,int v)
42 {
43     y=++cnt;
44     sum[y]=sum[x]+1;
45     if(l==r)return;
46     ls[y]=ls[x];rs[y]=rs[x];
47     int mid=(l+r)>>1;
48     if(v<=mid)update(l,mid,ls[x],ls[y],v);else update(mid+1,r,rs[x],rs[y],v);
49 }
50 inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
51 void dfs(int x)
52 {
53     vis[x]=1;
54     for(int i=head[x],y;i;i=e[i].next)
55      if(!vis[y=e[i].go])
56       {
57           update(1,n,root[x],root[y],b[y]);
58           dfs(y);
59           fa[y]=x;
60       }
61     int t=q[x].size();
62     for0(i,t-1)if(vis[q[x][i].first])lca[q[x][i].second]=find(x);
63 }
64 inline bool cmp(int x,int y){return a[x]<a[y];}
65 int main()
66 {
67     freopen("input.txt","r",stdin);
68     freopen("output.txt","w",stdout);
69     n=read();m=read();
70     for1(i,n)a[i]=read(),id[i]=i;
71     sort(id+1,id+n+1,cmp);
72     for1(i,n)b[id[i]]=i;
73     for1(i,n-1)insert(read(),read());
74     for1(i,m)
75      {
76          u[i]=read();v[i]=read();rk[i]=read();
77          q[u[i]].push_back(pa(v[i],i));
78          q[v[i]].push_back(pa(u[i],i));
79      }
80     for1(i,n)fa[i]=i; 
81     update(1,n,0,root[1],b[1]);
82     dfs(1);
83     int ans=0;
84     for1(i,m)
85      {
86         int x=root[u[i]],y=root[v[i]],xx=root[lca[i]],yy=root[fa[lca[i]]],l=1,r=n,k=rk[i];
87         while(l!=r)
88         {
89             int t=sum[ls[x]]+sum[ls[y]]-sum[ls[xx]]-sum[ls[yy]],mid=(l+r)>>1;
90             if(t>=k){x=ls[x];y=ls[y];xx=ls[xx];yy=ls[yy];r=mid;}
91             else {x=rs[x];y=rs[y];xx=rs[xx];yy=rs[yy];l=mid+1;k-=t;}
92         }
93         ans=l;
94         printf("%d\n",a[id[ans]]);
95      }
96     return 0;
97 }
View Code

在线的话其实没多大区别

相关文章:

  • 2021-11-24
  • 2021-08-15
  • 2021-10-16
  • 2021-12-01
  • 2021-06-25
  • 2021-06-24
  • 2021-06-23
  • 2022-12-23
猜你喜欢
  • 2021-06-18
  • 2021-11-08
  • 2021-11-25
  • 2021-12-03
相关资源
相似解决方案