Count on the path
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 378 Accepted Submission(s): 113
Problem Description
bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n.
Let f(a,b) be the minimum of vertices not on the path between vertices a and b.
There are q queries (u i,v i) for the value of f(u i,v i). Help bobo answer them.
Let f(a,b) be the minimum of vertices not on the path between vertices a and b.
There are q queries (u i,v i) for the value of f(u i,v i). Help bobo answer them.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,q (4≤n≤10 6,1≤q≤10 6). Each of the following (n - 1) lines contain 2 integers a i,b i denoting an edge between vertices a i and b i(1≤a i,b i≤n). Each of the following q lines contains 2 integer u′ i,v′ i (1≤u i,v i≤n).
The queries are encrypted in the following manner.
u 1=u′ 1,v 1=v′ 1.
For i≥2, u i=u′ i⊕f(u i - 1,v i - 1),v i=v′ i⊕f(u i-1,v i-1).
Note ⊕ denotes bitwise exclusive-or.
It is guaranteed that f(a,b) is defined for all a,b.
The task contains huge inputs. `scanf` in g++ is considered too slow to get accepted. You may (1) submit the solution in c++; or (2) use hand-written input utilities.
The first line contains 2 integers n,q (4≤n≤10 6,1≤q≤10 6). Each of the following (n - 1) lines contain 2 integers a i,b i denoting an edge between vertices a i and b i(1≤a i,b i≤n). Each of the following q lines contains 2 integer u′ i,v′ i (1≤u i,v i≤n).
The queries are encrypted in the following manner.
u 1=u′ 1,v 1=v′ 1.
For i≥2, u i=u′ i⊕f(u i - 1,v i - 1),v i=v′ i⊕f(u i-1,v i-1).
Note ⊕ denotes bitwise exclusive-or.
It is guaranteed that f(a,b) is defined for all a,b.
The task contains huge inputs. `scanf` in g++ is considered too slow to get accepted. You may (1) submit the solution in c++; or (2) use hand-written input utilities.
Output
For each tests:
For each queries, a single number denotes the value.
For each queries, a single number denotes the value.
Sample Input
4 1 1 2 1 3 1 4 2 3 5 2 1 2 1 3 2 4 2 5 1 2 7 6
Sample Output
4 3 1
Author
Xiaoxu Guo (ftiasch)
Source
题意:给你一棵树,最多有1e6个点。不断询问a->b外的最小点。
基本仿照gxx的标程来写的,感觉学到了很多。这题主要是考一些树上的细腻的操作。
思路见注释
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
#define INF 1e9
#define MAXN 21
const int maxn = 1000005;
#define mod 1000000007
#define eps 1e-7
#define pi 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
//ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int q[maxn];
int path[maxn]; //path[i]记录表示在i所在的子树中(以1为根),除i到1这条路径外的最小值
int child[maxn][4]; //child[i][0]表示以i为根且不包括i的树的最小点,child[i][1]为次小,child[i][2]为第三小
int fa[maxn];
int belong[maxn]; //belong[i]表示i所在的子树(以1为根)的最小值,可用来快速判断两点是否位于同一子树
int subtree[maxn];//subtree[i]表示以i为根(包括i)的子树的最小值
vector<int> G[maxn]; //邻接表
int n,m;
int next_int()
{
int result = 0;
char c = getchar();
while (!isdigit(c)) {
c = getchar();
}
while (isdigit(c)) {
result = result * 10 + c - '0';
c = getchar();
}
return result;
}
int query(int a,int b)
{
if(a > b) swap(a,b);
if(a != 1 && (belong[a] == belong[b])) return 1; //若两点位于同一子树,则不经过1
int i = 0;
while(child[1][i] == belong[a] || child[1][i] == belong[b]) i++; //找出除a,b所在子树外最小的点
int ans = a == 1 ? path[b] : min(path[a], path[b]); //a,b所在子树最小的点(a->1,b->1的路径除外)
ans = min(ans, child[1][i]);
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&m))
{
int a,b;
rep(i,n+1) G[i].clear();
rep(i,n-1)
{
a = next_int();
b = next_int();
G[a].push_back(b); //用了vector保存邻接表,不断pb g++T了,用C++过了
G[b].push_back(a);
}
int head = 0, tail = 0;
q[tail++] = 1;
fa[1] = -1;
while(head < tail)
{
int u = q[head++];
for(int i = 0;i <(int)G[u].size(); i++)
{
int v = G[u][i];
if(v == fa[u]) continue;
fa[v] = u;
q[tail++] = v;
}
}
rep1(i,n) rep(j,4) child[i][j] = INF;
for(int i = tail-1; i >= 0; i--)
{
int v = q[i];
subtree[v] = min(child[v][0], v);
int u = fa[v];
if(u != -1)
{
child[u][3] = subtree[v];
sort(child[u], child[u] + 4);
//path[v] = min(child[u][0]
}
}
head = tail = 0;
for(int i = 0;i < (int)G[1].size(); i++)
{
int u = G[1][i];
belong[u] = subtree[u];
path[u] = INF;
q[tail++] = u;
}
path[1] = INF;
belong[1] = -1;
while(head < tail)
{
int u = q[head++];
for(int i = 0;i < (int)G[u].size(); i++)
{
int v = G[u][i];
if(v == fa[u]) continue;
belong[v] = belong[u];
path[v] = min(path[u], child[u][subtree[v] == child[u][0]]);
q[tail++] = v;
}
path[u] = min(path[u], child[u][0]);
}
int last = 0;
while(m--)
{
a = next_int();
b = next_int();
a ^= last;
b ^= last;
int ans = query(a,b);
last = ans;
printf("%d\n",ans);
}
}
return 0;
}