求调,树上莫队 TLE
查看原帖
求调,树上莫队 TLE
363036
chlchl楼主2022/12/30 16:07

显示 0.00s,难道 map真的这么慢吗???

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
const int M = 2e5 + 10;
int n, m, blk, col[N], dep[N], f[N][17];
int clk, in[N], out[N], euler[N << 1];
int id, head[N << 1], nxt[N << 1], to[N << 1];
int tot, ans[M];
map<int, int> tcol;
bool vis[N];
struct event{
	int s, t, idx;
	bool operator < (const event &p) const {
		if(s / blk != p.s / blk)  return s < p.s;
    	return t < p.t;
	}
} q[M];

void add(int u, int v){
	to[++id] = v;
	nxt[id] = head[u], head[u] = id;
}

void dfs(int u, int fa){
	f[u][0] = fa;
	in[u] = ++clk, euler[clk] = u;
	for(int i=1;i<=16;i++)
		f[u][i] = f[f[u][i - 1]][i - 1];
	for(int i=head[u];i;i=nxt[i]){
		int v = to[i];
		if(v == fa)
			continue;
		dep[v] = dep[u] + 1;
		dfs(v, u);
	}
	out[u] = ++clk, euler[clk] = u;
}

int lca(int u, int v){
	if(dep[u] < dep[v])
		swap(u, v);
	for(int i=16;i>=0;i--)
		if(dep[f[u][i]] >= dep[v])
			u = f[u][i];
	if(u == v)
		return u;
	for(int i=16;i>=0;i--)
		if(f[u][i] != f[v][i])
			u = f[u][i], v = f[v][i];
	return f[u][0];
}

void calc(int k){
	if(vis[k]){
		--tcol[col[k]];
		if(tcol[col[k]] == 0)
			--tot;
	}
	else{
		++tcol[col[k]];
		if(tcol[col[k]] == 1)
			++tot;
	}
	vis[k] ^= 1;
}

int main(){
	scanf("%d%d", &n, &m);
	for(int i=1;i<=n;i++)
		scanf("%d", &col[i]);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d", &u, &v);
		add(u, v), add(v, u);
	}
	dfs(1, 0);
//	for(int i=1;i<=clk;i++)
//		cout << euler[i];
	blk = sqrt(clk);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d", &u, &v);
		if(dep[u] > dep[v])
			swap(u, v);
		if(lca(u, v) == u)
			q[i] = (event){in[u], in[v], i};
		else
			q[i] = (event){out[u], in[v], i};
	}
	sort(q + 1, q + 1 + m);
//	for(int i=1;i<=m;i++)
//		cout << q[i].s << ' ' << q[i].t << endl;
	int l = 1, r = 0;
	for(int i=1;i<=m;i++){
		while(r < q[i].t)
			calc(euler[++r]);
		while(l > q[i].s)
			calc(euler[--l]);
		while(r > q[i].t)
			calc(euler[r--]);
		while(l < q[i].s)
			calc(euler[l++]);
		int chl = lca(euler[q[i].s], euler[q[i].t]);
		ans[q[i].idx] = tot + (tcol[col[chl]] == 0);
	}
	for(int i=1;i<=m;i++)
		printf("%d\n", ans[i]);
	return 0;
}
2022/12/30 16:07
加载中...