Loading

【题解】[CCO2021] Through Another Maze Darkly

nb的树上思维DS题。

如果我们把每个指针的的指向集合作为状态,由于状态集合是有限的,并且相同的初始状态则结束位置相同,所以最后一定会循环。但是并不一定是纯循环。

由于这是一颗树,所以我们考虑特殊性质。如果是一个菊花图,显然就是一个排列不断循环。如果是链,手算一下发现就是从点 \(1\) 开始,不断来回向两边扩展。每次扩展多少取决于指针的指向。

所以我们定义 \(f_i\) 表示节点 \(i\) 的重标号,按一下方式标号。

对于当前点 \(i\) ,它父亲前面出现的子节点标号为它的标号,后面出现的标号要\(+1\)

然后我们再求整个树的 DFS 序,注意 DFS 序是唯一的,每次我们从父节点顺时针的下一个子节点开始。

这样标号,我们就构造出了整个路径。我们按以下方式还原路径。

定义 \(s_i\) 表示标号 \(\le i\) 的点在 DFS 序中出现的位置连起来,那么原路径就是 \(s_1s_2\cdots\)

所以从 \(s_n\) 开始就一直以 \(s_n\) 循环,对于前面的可以直接可持久化线段树维护 \(s_i\),二分后再在线段树上二分可以做到时空复杂度 \(\mathcal{O}(N\log N)\)。事实上可以对询问离线,可以将空间优化到线性,但是本题有一个G所以无所谓。

/*
    Author : SharpnessV
    Right Output ! & Accepted !
*/
#include<bits/stdc++.h>
//#define int long long

#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define pre(i, a, b) for(int i = (a);i >= (b);i--)
#define rp(i, a) for(int i = 1; i <= (a); i++)
#define pr(i, a) for(int i = (a); i >= 1; i--)
#define go(i, x) for(auto i : x)

#define mp make_pair
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define ze(p) memset(p, 0, sizeof(p))
#define mem(p, x) memset(p, x, sizeof(p))
#define YES puts("YES")
#define NO puts("NO")
#define Yes puts("Yes")
#define No puts("No")
#define si(x) (int)(x).size()
#define db cerr
#define pc putchar
#define gc getchar
#define el putchar('\n')

using namespace std;
const double eps = 1e-15, pi = 3.1415926535897932385;
typedef long long LL;
typedef pair<int,int> Pr;
const int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1}, inf = 0x7fffffff;
//Author : SharpnessV
//#define main Solution
char buf[1<<22],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read(){
    int x = 0;bool f = 1;char ch = gc();
    while(!isdigit(ch))f = ('-' == ch ? 0 : 1), ch = gc();
    while(isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
    if(f)return x;return -x;
}
inline LL Read(){
    LL x = 0;bool f = 1;char ch = gc();
    while(!isdigit(ch))f = ('-' == ch ? 0 : 1), ch = gc();
    while(isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
    if(f)return x;return -x;
}
int gcd(int x,int y){return y ? gcd(y, x % y) : x;}
int lcm(int x,int y){return x / gcd(x, y) * y;}
#define P 1000000007
//#define P 998244353
#define bas 229
inline void ad(int &x, int y){x += y; if(x >= P) x -= P;}
inline void su(int &x, int y){x -= y; if(x < 0) x += P;}
inline void cmn(int &x,int y){if(y < x) x = y;}
inline void cmx(int &x,int y){if(y > x) x = y;}
inline void cmn(LL &x, LL y){if(y < x) x = y;}
inline void cmx(LL &x, LL y){if(y > x) x = y;}

int Pow(int x, int y){
	if(y < 0)return Pow(Pow(x, P - 2), -y);
	int now = 1 ;
	for(;y;y >>= 1, x = 1LL * x * x % P)if(y & 1) now = 1LL * now * x % P;
	return now;
}

/*******************************************************************************************************************/
/*                                                                                                                 */
/*******************************************************************************************************************/

#define N 800005
#define M 40000005

int n, q, deg[N], u[N << 1], d[N], idx, m;LL s[N];
vector<int>e[N], c[N << 1];

void dfs(int x,int fa){
	if(x != 1)u[++idx] = x, c[d[x]].pb(idx), cmx(m, d[x]);
	bool flag = 0;
	go(y, e[x]){
		if(y == fa)flag = 1;
		else if(flag)d[y] = d[x] + 1, dfs(y, x), u[++idx] = x, c[d[y]].pb(idx);
	}
	go(y, e[x]){
		if(y == fa)break;
		d[y] = d[x], dfs(y, x), u[++idx] = x, c[d[y]].pb(idx);
	}
}

struct Node{
	int l, r, val;
}a[M];

#define ls a[x].l
#define rs a[x].r
#define S a[x].val

int tot, rt[N];

void ins(int &x,int l,int r,int pos){
	int y = x; x = ++tot, a[x] = a[y];
	if(l == r)S = 1;
	else{
		int mid = (l + r) >> 1;
		if(mid >= pos)ins(ls, l, mid, pos);
		else ins(rs, mid + 1, r, pos);
		S = a[ls].val + a[rs].val;
	}
}

void ask(int x,int l,int r,int k){
	if(l == r)printf("%d\n", u[l]);
	else{
		int mid = (l + r) >> 1;
		if(a[ls].val >= k)ask(ls, l, mid, k);
		else ask(rs, mid + 1, r, k - a[ls].val);
	}
}

int main(){
	//freopen("d1p3.4-42.in","r",stdin);
	//freopen("OUTPUT","w",stdout);
	//int T = read();while(T--)solve();
	n = read(), q = read();
	rp(i, n){
		deg[i] = read();int x = read();
		rp(j, deg[i] - 1)e[i].pb(read());
		e[i].pb(x);
	}
	d[1] = 1, dfs(1, 0);
	rt[0] = ++tot;
	rp(i, m){
		rt[i] = rt[i - 1];
		go(y, c[i])ins(rt[i], 1, idx, y);
		s[i] = s[i - 1] + si(c[i]);
	}
	rp(i, m)s[i] += s[i - 1];
	//rp(i, idx)printf("%d ",u[i]);el;
	//rp(i, idx)printf("%d ",w[i]);el;
	//rp(i, n)printf("%d ",d[i]);el;
	while(q--){
		LL x = Read();
		if(x > s[m]){
			x = (x - s[m - 1]) % (s[m] - s[m - 1]);
			if(!x)x = s[m] - s[m - 1];
			ask(rt[m], 1, idx, x);
		}
		else{
			int l = 1, r = m, ed = 0;
			while(l <= r){
				int mid = (l + r) >> 1;
				if(s[mid - 1] < x)ed = mid, l = mid + 1;
				else r = mid - 1; 
			}
			x -= s[ed - 1];
			ask(rt[ed], 1, idx, x);
		}
	}
	return 0;
}
posted @ 2021-08-27 22:11  7KByte  阅读(150)  评论(0编辑  收藏  举报