想问一下自己的思路和代码
查看原帖
想问一下自己的思路和代码
2876
MifuneShioriko楼主2020/11/5 00:49

看到一大片题解都是开两个bit 自己有一个略有区别的想法 考虑依然不让一个点被染色两次,当x有子树被染颜色y之后要把x的子树染色,就把有该颜色的子树答案撤销,再更新x(题解做法) 然后我觉得这里可以直接开一棵线段树做,对染x,如果祖先被染过了就不管他,如果有v在x的子树内被染色了,就update(dfn[v],low[v],1)update(dfn[v],low[v],-1),最后统一update(dfn[x],low[x],1)update(dfn[x],low[x],1) 统计答案只要维护区间和,query(dfn[x],low[x])就行了吧,感觉思路没啥问题 然后代码交上去14分 很离谱 大概是那种 在几k行出现了答案缺1多1的情况 不太懂什么情况

附上代码,要是大佬有时间愿意帮看一下就更好了,谢谢各位

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<set>
#define rep(i,x,y) for (int i=x;i<=y;i++)
using namespace std;
typedef long long ll;
const int maxn=100010;
ll sum[maxn<<2],lazy[maxn<<2];
int dfn[maxn],low[maxn],dc=0,link[maxn],n,q,head[maxn],cnt=0;
struct Edge{int v,nex;}edge[maxn<<1];
set<int> col[maxn];
inline void addEdge(int u,int v){
    edge[++cnt]=(Edge){v,head[u]};head[u]=cnt;
}
void dfs(int u){
	dfn[u]=++dc;link[dc]=u;
	for (int i=head[u];i;i=edge[i].nex){
		int v=edge[i].v;
		if (!dfn[v]) dfs(v);
	}
	low[u]=dc;
}
#define lc root<<1
#define rc root<<1|1
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
void pushdown(int root,int l,int r){
	ll t=lazy[root],mid=l+r>>1;lazy[root]=0;
	lazy[lc]+=t;lazy[rc]+=t;
	sum[lc]+=1ll*(mid-l+1)*t;sum[rc]+=1ll*(r-mid)*t;
}
void update(int L,int R,int delta,int root,int l,int r){
	if (L<=l && r<=R){
		sum[root]+=1ll*delta*(r-l+1);
		lazy[root]+=delta;
		return;
	}
	if (lazy[root]!=0) pushdown(root,l,r);
	int mid=l+r>>1;
	if (L<=mid) update(L,R,delta,lson);
	if (R>mid)  update(L,R,delta,rson);
	sum[root]=sum[lc]+sum[rc];
}
ll query(int L,int R,int root,int l,int r){
	//printf("%d %d %d\n",root,l,r);
	if (L<=l && r<=R) return sum[root];
	int mid=l+r>>1;ll ans=0;
	if (lazy[root]!=0) pushdown(root,l,r);
	if (L<=mid) ans+=query(L,R,lson);
	if (R>mid)  ans+=query(L,R,rson);
	return ans;
}
int read(){
	int x=0;char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=x*10+ch-48,ch=getchar();
	return x;
}
int main(){
    n=read();q=read();
    rep(i,1,n-1){
        int x=read(),y=read();
        addEdge(x,y);addEdge(y,x);
    }
	dfs(1);
	memset(sum,0,sizeof(sum));memset(lazy,0,sizeof(lazy));
    while (q--){
		int opt=read(),x=read();
		if (opt&1){
			int y=read();//a color
			set<int>::iterator it=col[y].upper_bound(dfn[x]);
			if (it!=col[y].begin() && low[link[*(--it)]]>=low[x]) continue;//ancestor
			while (it!=col[y].end() && low[link[*it]]<=low[x]){
				update(dfn[link[*it]],low[link[*it]],-1,1,1,n);
				col[y].erase(it);
				it=col[y].upper_bound(dfn[x]);
			}
			update(dfn[x],low[x],1,1,1,n);col[y].insert(dfn[x]);
		}else 
			printf("%lld\n",query(dfn[x],low[x],1,1,n));
	}
	return 0;
}
2020/11/5 00:49
加载中...