样例没过,求调,悬一关
查看原帖
样例没过,求调,悬一关
1045961
穼柗°楼主2025/2/8 09:27

样例的输出全是 1,用的是线段树+树剖,求调。

#include <iostream>
#include <vector>
#include <tuple>
#define fswap(x,y) x^=y^=x^=y // <=> swap(x,y)

using namespace std;
using cint= const int;
static cint N=100001;
struct info { // 维护线段树上的区间信息
    int val,lft,rit; // 分别表示 颜色段数量,左端点,右端点
    info(cint val,cint lft,cint rit): val(val),lft(lft),rit(rit) {}
    info(cint val=0): val(1),lft(val),rit(val) {}
    info operator +(const info &o) const { // 合并序列
        if(!val) return o;
        else if(!o.val) return *this;
        else return info(val+o.val-(rit==o.lft?1:0),lft,o.rit);
    }
    inline info reverse() { // 反转序列
        fswap(lft,rit);
        return *this;
    }
};
class segment_tree { // 区间赋值,查询颜色段数量的线段树
    info val[N<<2];
	int n,*a,tag[N<<2];
	void __build(cint u,cint l,cint r) {
		if(l==r) {val[u]=a[l];return;}
		cint mid=(l+r)>>1;
		__build(u<<1,l,mid);
		__build(u<<1|1,mid+1,r);
        val[u]=val[u<<1]+val[u<<1|1];
	}
	void __apply(cint u,cint l,cint r,cint x) {
        if(x>=0)
            tag[u]=x,val[u]=x;
	}
	void __pushdown(cint u,cint l,cint r) {
		if(tag[u]) {
			cint mid=(l+r)>>1;
			__apply(u<<1,l,mid,tag[u]);
			__apply(u<<1|1,mid+1,r,tag[u]);
			tag[u]=-1;
		}
	}
	void __upd(cint u,cint l,cint r,cint s,cint t,cint x) {
		if(s<=l&&r<=t) {__apply(u,l,r,x);return;}
		__pushdown(u,l,r);
		cint mid=(l+r)>>1;
		if(s<=mid) __upd(u<<1,l,mid,s,t,x);
		if(t>mid) __upd(u<<1|1,mid+1,r,s,t,x);
        val[u]=val[u<<1]+val[u<<1|1];
	}
	info __query(cint u,cint l,cint r,cint s,cint t) {
		if(s<=l&&r<=t) return val[u];
		cint mid=(l+r)>>1;
		__pushdown(u,l,r);
		if(t<=mid) return __query(u<<1,l,mid,s,t);
		if(s>mid) return __query(u<<1|1,mid+1,r,s,t);
		return __query(u<<1,l,mid,s,t)+__query(u<<1|1,mid+1,r,s,t);
	}
	public:
	segment_tree(cint n=0,int *a=nullptr): n(n),a(a) {
		if(a) __build(1,1,n);
	}
	inline void resize(cint __n,int *__a) {
		n=__n,a=__a;
		__build(1,1,n);
        for(int &i: tag)
            i=-1;
	}
	inline void upd(cint s,cint t,cint x) {
		__upd(1,1,n,s,t,x);
	}
	inline info query(cint s,cint t) {
		return __query(1,1,n,s,t).val;
	}
};
segment_tree st;
vector<int> g[N]; // vector 存树
int n,m,clk,sz[N],dep[N],top[N],fa[N],son[N],dfn[N];
// sz[]:子树大小;dep[]:结点深度;top[]:结点对应的链顶;fa[]:父节点;son[]重子节点;dfn[]重边优先遍历的dfs序
void dfs1(cint u) { // 求 dep[],sz[],fa[],son[]
	sz[u]=1;
	for(auto v: g[u])
		if(v!=fa[u]) {
			dep[v]=dep[u]+1,
			fa[v]=u;
			dfs1(v);
			sz[u]+=sz[v];
			if(sz[v]>sz[son[u]]) son[u]=v;
		}
}
void bui(cint u,cint t) { // 求 dfn[],top[]
	dfn[u]=++clk,top[u]=t;
	if(son[u]) bui(son[u],t);
	for(auto v: g[u])
		if(v!=fa[u]&&v!=son[u])
            bui(v,v);
}
int arr[N],a[N];
void paint(int u,int v,int w) { // 染色
	while(top[u]!=top[v]) {
		if(dep[top[u]]<dep[top[v]]) fswap(u,v);
		st.upd(dfn[top[u]],dfn[u],w);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v]) fswap(u,v);
	st.upd(dfn[v],dfn[u],w);
}
int cnt(int u,int v) { // 统计答案
    info x(0,0,0),y(0,0,0);
    while(top[u]!=top[v]) {
        if(dep[top[u]]>dep[top[v]]) x=st.query(dfn[top[u]],dfn[u])+x,u=fa[top[u]];
        else y=st.query(dfn[top[v]],dfn[v])+y,v=fa[top[v]];
    }
    if(dep[u]>dep[v]) x=st.query(dfn[v],dfn[u])+x;
    else y=st.query(dfn[u],dfn[v])+y;
    return (x.reverse()+y).val;
}
void init(cint root) { // 树剖
	dfs1(root);
	bui(root,root);
    for(int i=1;i<=n;i++)
        arr[dfn[i]]=a[i];
    st.resize(n,arr);
}
int main() {
	cin.tie(nullptr)->sync_with_stdio(false),
	cout.tie(nullptr);
	cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
	for(int u,v,w,i=1;i<n;i++) {
		cin>>u>>v;
		g[u].push_back(v),
		g[v].push_back(u);
	}
	init(1);
    string op;
	for(int a,b,c;m--;) {
		cin>>op>>a>>b;
        if(op=="C") {
            cin>>c;
            paint(a,b,c);
        } else {
            cout<<cnt(a,b)<<'\n';
        }
	}
	return 0;
}
2025/2/8 09:27
加载中...