社区讨论
【悬关】关于Oi-wiki上U41492 树上数颜色 其他做法的疑问
题目总版参与者 3已保存回复 6
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 6 条
- 当前快照
- 1 份
- 快照标识符
- @mhjhwfqd
- 此快照首次捕获于
- 2025/11/04 02:50 4 个月前
- 此快照最后确认于
- 2025/11/04 02:50 4 个月前
oi-wiki 出处 树上数颜色
洛谷出处 树上数颜色
事实上,只需要使用最简单的dfs遍历便可以使得同一子树内的dfn序连续。因此性质,不难联想到扫描线经典老题目 P1972 [SDOI2009] HH的项链 ,我们可以以dfn序建立一个新序列,节点 子树的颜色种数就是统计区间 内颜色的数量。
通过询问教练 @Hevix 以及 将写出来的WA代码投喂给AI(Google Gemini)后均指出思路并无问题。
错误点补充:
- 我的输出的答案可以过样例,但是输出的值与实际答案要么多 ,要么少 。
- 经过多次检查,线段树没有问题(build,nodesum,modifyadd等)。对于nodesum询问函数,其实加不加pushup(p) 都无影响。
- WA 具体信息
恳请洛谷各位犇犇救救本蒟蒻,十分感激!!!
CPP#include<bits/stdc++.h>
#define endl '\n'
#define MIN(a,b,c) min(min(a,b),c)
#define MAX(a,b,c) max(max(a,b),c)
#define ri register int
#define int long long
#define fixedset(a) fixed << setprecision(a)
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
#define ls(x) x<<1
#define rs(x) x<<1|1
#define MAXN 9.2211e18
#define inf 114514
#define mf 5011
#define sf 1011
#define eps 1e-7
#define MOD 114514
#define mod(x) (x+MOD)%MOD
using namespace std;
mt19937_64 randint{std::chrono::steady_clock::now().time_since_epoch().count()};
struct Msg{
int val,l,r;
Msg():val(0),l(0),r(0){}
Msg(int VAL,int L,int R):val(VAL),l(L),r(R){}
Msg operator +(const Msg &p) const{
return {val+p.val,l,p.r};
}
}msg[(inf+sf)*4];
struct Tag{
int add;
Tag():add(0){}
Tag(int ADD):add(ADD){}
Tag operator <(const Tag &p) const{
return {add+p.add};
}
Msg apply(const Msg &p) const{
return {p.val+add*(p.r-p.l+1),p.l,p.r};
}
}tag[(inf+sf)*4];
int n,m,tmp[inf],num[inf],lst[inf],suf[inf],ans[inf];
vector<tuple<int,int,int> > modify[inf];
vector<tuple<int,int> > query[inf];
vector<int> edge[inf];
int cnt,siz[inf],dfn[inf],rnk[inf];
void pushup(int p){
msg[p]=msg[ls(p)]+msg[rs(p)];
return ;
}
void pushdown(int p){
msg[ls(p)]=tag[p].apply(msg[ls(p)]); msg[rs(p)]=tag[p].apply(msg[rs(p)]);
tag[ls(p)]=tag[ls(p)]<tag[p]; tag[rs(p)]=tag[rs(p)]<tag[p];
tag[p]=Tag();
return ;
}
void build(int p,int s,int t){
if(s==t){
msg[p]=Msg(0,s,t);
return ;
}
int mid=s+((t-s)>>1);
build(ls(p),s,mid);
build(rs(p),mid+1,t);
pushup(p);
return ;
}
void modifyadd(int p,int s,int t,int l,int r,Tag c){
if(l<=s && t<=r){
msg[p]=c.apply(msg[p]);
tag[p]=tag[p]<c;
return ;
}
int mid=s+((t-s)>>1);
pushdown(p);
if(l<=mid) modifyadd(ls(p),s,mid,l,r,c);
if(r >mid) modifyadd(rs(p),mid+1,t,l,r,c);
pushup(p);
return ;
}
Msg nodesum(int p,int s,int t,int g){
if(s==t) return msg[p];
int mid=s+((t-s)>>1);
pushdown(p); Msg res;
if(g<=mid) res=res+nodesum(ls(p),s,mid,g);
if(g >mid) res=res+nodesum(rs(p),mid+1,t,g);
pushup(p);
return res;
}
int dfs(int u,int fa){
cnt++; siz[u]++;
dfn[u]=cnt,rnk[cnt]=u;
for(auto v:edge[u]){
if(v==fa) continue;
siz[u]+=dfs(v,u);
}
return siz[u];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
cin >> n;
for(ri i=2;i<=n;i++){
int x,y; cin >> x >> y;
edge[x].push_back(y); edge[y].push_back(x);
}
for(ri i=1;i<=n;i++) cin >> tmp[i];
dfs(1,0); build(1,1,n); cin >> m;
for(ri i=1;i<=n;i++) num[dfn[i]]=tmp[i];
for(ri i=1;i<=n;i++) lst[i]=n+1;
for(ri i=n;i>=1;i--){
suf[i]=lst[num[i]];
lst[num[i]]=i;
modify[1].push_back({i,suf[i]-1,1});
modify[i+1].push_back({i,suf[i]-1,-1});
}
for(ri i=1;i<=m;i++){
int x; cin >> x;
query[dfn[x]].push_back({dfn[x]+siz[x]-1,i});
}
for(ri i=1;i<=n;i++){
for(auto [l,r,c]:modify[i]) modifyadd(1,1,n,l,r,Tag(c));
for(auto [g,id]:query[i]) ans[id]=nodesum(1,1,n,g).val;
}
for(ri i=1;i<=m;i++) cout << ans[i] << endl;
return 0;
}
回复
共 6 条回复,欢迎继续交流。
正在加载回复...