社区讨论

萌新初学树剖,阳历过但是全WA求条

P2486[SDOI2011] 染色参与者 5已保存回复 16

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
15 条
当前快照
1 份
快照标识符
@mm0av6cq
此快照首次捕获于
2026/02/24 15:44
2 周前
此快照最后确认于
2026/02/26 09:05
2 周前
查看原帖
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,tot,a[400005],dep[400005],up[400005],sz[400005],in[400005],fa[400005];//a初始权值,dep深度,up链顶,sz子树大小,in时间戳(dfn),fa父亲
vector<int> g[400005];//树
struct Segment_tree{//炒鸡柯哀的线段树
    struct node{int l,r,lazy,st,ed,sum = 1;}a[1600005];
    void build(int op,int l,int r){
    	a[op].l = l;
    	a[op].r = r;
    	if (l == r) return;
    	int mid = (l + r) / 2;
    	build(op * 2,l,mid);
    	build(op * 2 + 1,mid + 1,r);
    }
    void spread(int op){if (a[op].l != a[op].r && a[op].lazy){
        a[op].sum = 1;
        a[op * 2].lazy = a[op * 2 + 1].lazy = a[op].st = a[op].ed = a[op].lazy;
        a[op].lazy = 0;
    }}//pushdown
    void pushup(int op){
        a[op].sum = a[op * 2].sum + a[op * 2 + 1].sum - (a[op * 2].ed == a[op * 2 + 1].st);
        a[op].st = a[op * 2].st;
        a[op].ed = a[op * 2 + 1].ed;
    }
    void change(int op,int l,int r,int x){
        if (l <= a[op].l && a[op].r <= r){
            a[op].sum = 1;
            a[op].st = a[op].ed = a[op].lazy = x;
            return;
        }
        spread(op);
    	int mid = (a[op].l + a[op].r) / 2;
    	if (l <= mid) change(op * 2,l,r,x);
    	if (mid < r) change(op * 2 + 1,l,r,x);
    	pushup(op);
    }
    array<int,3> query(int op,int l,int r){//华为三折叠
    	if (l <= a[op].l && a[op].r <= r) return {a[op].sum,a[op].st,a[op].ed};
        spread(op);
    	int mid = (a[op].l + a[op].r) / 2,ans = 0,ast = 0,aed = 0;
    	if (l <= mid){
            array<int,3> tmp = query(op * 2,l,r);
            ans = tmp[0];
            ast = tmp[1];
            aed = tmp[2];
        }
    	if (mid < r){
            if (ans) ans -= a[op * 2].ed == a[op * 2 + 1].st;
            array<int,3> tmp = query(op * 2 + 1,l,r);
            ans += tmp[0];
            if (!ast) ast = tmp[1];
            aed = tmp[2];
        }
    	return {ans,ast,aed};
    }
}tree;
void dfs1(int x,int f){
    dep[x] = dep[f] + 1;
    sz[x] = 1;
    fa[x] = f;
    for (int i = 0; i < g[x].size(); i++){
        int nxt = g[x][i];
        if (nxt != f){
            dfs1(nxt,x);
            sz[x] += sz[nxt];
        }
    }
}
void dfs2(int x,int u){
    up[x] = u;
    in[x] = ++tot;
    tree.change(1,in[x],in[x],a[x]);//给线段树赋出世权值
    sort(g[x].begin(),g[x].end(),[](int x,int y){return sz[x] > sz[y];});
    for (int i = 0; i < g[x].size(); i++){
        int nxt = g[x][i];
        if (nxt != fa[x]) dfs2(nxt,i == (x != 1) ? u : nxt);
    }
}//熟练剖粪
void modify(int x,int y,int z){
    while (up[x] != up[y]){
        if (dep[up[x]] < dep[up[y]]) swap(x,y);
        tree.change(1,in[up[x]],in[x],z);
        x = fa[up[x]];
    }
    tree.change(1,min(in[x],in[y]),max(in[x],in[y]),z);
}//C
int ask(int x,int y){
    int res = 0,xed = 0,yed = 0;
    while (up[x] != up[y]){
        if (dep[up[x]] < dep[up[y]]){
            swap(x,y);
            swap(xed,yed);
        }
        array<int,3> tmp = tree.query(1,in[up[x]],in[x]);
        res += tmp[0] - (tmp[1] == xed);
        xed = tmp[2];
        x = fa[up[x]];
    }
    if (in[x] > in[y]) swap(x,y);
    array<int,3> tmp = tree.query(1,in[x],in[y]);
    return res + tmp[0] - (xed == tmp[1]) - (yed == tmp[2]);
}//Q
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    tree.build(1,1,n);//厨师话
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1,x,y; i < n; i++){
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs1(1,0);
    dfs2(1,1);
    for (int x,y,z; m--; ){
        char op;
        cin >> op >> x >> y;
        if (op == 'C'){
            cin >> z;
            modify(x,y,z);
        }
        else cout << ask(x,y) << '\n';
    }
    return 0;
}

回复

16 条回复,欢迎继续交流。

正在加载回复...