社区讨论
求问站外(玄关)
学术版参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mlrgo6sl
- 此快照首次捕获于
- 2026/02/18 11:17 昨天
- 此快照最后确认于
- 2026/02/18 23:12 18 小时前
题目描述
树之国有 个城市,编号为 到 , 条无向道路连接着这些城市,任意两个城市之间都可以互相到达。有 个商人在树之国进行着商业活动,第 个商人会在 号城市到 号城市的简单路径(包括 号和 号城市)上活动。如果两个商人的活动范围有重合,他们可以进行交易,请你对每个商人求出有多少个商人可以和他交易。
输入格式
第一行两个正整数 。
接下来 行,每行两个正整数,表示一条道路的两个端点。
接下来 行,每行两个正整数,其中第 行为 。
接下来 行,每行两个正整数,表示一条道路的两个端点。
接下来 行,每行两个正整数,其中第 行为 。
输出格式
输出 行,每行一个整数,其中第 行表示有多少个其他商人能和第 个商人交易。
样例输入
TEXT4 3
1 2
2 3
3 4
1 2
2 3
3 4
样例输出
TEXT1
2
1
数据规模与约定
- 对于 的数据,。
- 对于 的数据,。
- 另有 的数据,第 条边连接 和 。
- 对于 的数据,。
我的代码
CPP#include<iostream>
#include<vector>
#include<cctype>
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char getc() {
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
int x = 0, f = 1;
char ch = getc();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getc();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getc();
}
return x * f;
}
inline void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
using namespace std;
int n,m;
const int N = 2e5 + 4;
vector<int> G[N];
int top[N],hson[N],siz[N];
int idx,dfn[N],f[N],dep[N];
int cnt[N],ans[N];
pair<int,int> v[N];
inline int max(int a,int b){
return a > b ? a : b;
}
inline int min(int a,int b){
return a > b ? b : a;
}
inline void Dfs1(int u,int fa){
dep[u] = dep[fa] + 1;
siz[u] = 1,f[u] = fa;
hson[u] = -1;
for(auto v : G[u]){
if(v == fa) continue;
Dfs1(v,u);
siz[u] += siz[v];
if(hson[u] == -1) hson[u] = v;
else if(siz[hson[u]] < siz[v]) hson[u] = v;
}
}
inline void Dfs2(int u,int t){
dfn[u] = ++ idx;
top[u] = t;
if(hson[u] != -1){
Dfs2(hson[u],t);
}
for(auto v : G[u]){
if(v == hson[u] || v == f[u]) continue;
Dfs2(v,v);
}
}
struct segment{
int l,r,sum,tag;
}t[N * 4];
inline void pushup(int p){
t[p].sum = t[p << 1].sum + t[p << 1 | 1].sum;
}
inline void pushdown(int p){
if(t[p].tag == 0) return ;
t[p << 1].tag += t[p].tag;
t[p << 1 | 1].tag += t[p].tag;
t[p << 1].sum += (t[p << 1].r - t[p << 1].l + 1) * t[p].tag;
t[p << 1 | 1].sum += (t[p << 1 | 1].r - t[p << 1 | 1].l + 1) * t[p].tag;
t[p].tag = 0;
}
inline void build(int p,int l,int r){
t[p].l = l,t[p].r = r;
if(l == r) return ;
int mid = l + r >> 1;
build(p << 1,l,mid),build(p << 1 | 1,mid + 1,r);
}
inline void add(int p,int l,int r){
if(t[p].l >= l && t[p].r <= r){
t[p].sum += t[p].r - t[p].l + 1;
t[p].tag ++;
return ;
}
pushdown(p);
int mid = t[p].l + t[p].r >> 1;
if(l <= mid)
add(p << 1,l,r);
if(r > mid)
add(p << 1 | 1,l,r);
pushup(p);
}
inline int qry(int p,int l,int r){
if(t[p].l >= l && t[p].r <= r) return t[p].sum;
pushdown(p);
int res = 0;
int mid = t[p].l + t[p].r >> 1;
if(l <= mid) res += qry(p << 1,l,r);
if(r > mid) res += qry(p << 1 | 1,l,r);
return res;
}
inline int flca(int x,int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x,y);
x = f[top[x]];
}
int l = (dep[x] > dep[y] ? y : x);
cnt[l] ++;
return l;
}
inline int lca(int x,int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x,y);
x = f[top[x]];
}
int l = (dep[x] > dep[y] ? y : x);
return l;
}
inline int qlca(int x,int y){
int res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x,y);
res += qry(1,dfn[top[x]],dfn[x]);
x = f[top[x]];
}
res += qry(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]));
return res;
}
inline void alca(int x,int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x,y);
add(1,dfn[top[x]],dfn[x]);
x = f[top[x]];
}
add(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]));
}
int main(){
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
n = read(),m = read();
for(register int i = 1;i < n;i += 1){
int u = read(),v = read();
G[u].push_back(v);
G[v].push_back(u);
}
Dfs1(1,0);
Dfs2(1,1);
build(1,1,n);
for(register int i = 1;i <= m;i += 1){
v[i].first = read(),v[i].second = read();
}
for(register int i = 1;i <= m;i += 1){
int l = flca(v[i].first,v[i].second);
alca(l,l);
}
int tim = 0;
for(register int i = 1;i <= m;i += 1){
ans[tim] += qlca(v[i].first,v[i].second);
tim ++;
}
for(register int i = 1; i <= 4 * n; i += 1){
t[i].sum = 0;
t[i].tag = 0;
}
for(register int i = 1;i <= m;i += 1){
alca(v[i].first,v[i].second);
}
tim = 0;
for(register int i = 1;i <= m;i += 1){
int l = lca(v[i].first,v[i].second);
ans[tim] += qlca(l,l);
write( ans[tim] - 1 - cnt[l] );
putchar('\n');
tim ++;
}
}
但是卡不过去常,他们说可以树上差分,求问怎么做或者你也可以帮我卡卡常thx
回复
共 0 条回复,欢迎继续交流。
正在加载回复...