[USACO19DEC]Bessie's Snow Cow

题目

显然这个子树操作是假的,我们dfs序一下就变成区间了

不难想到我们可以对于每一种颜色维护一个set,表示序列里哪些位置被涂上了这种颜色;对于修改操作,我们去对应颜色的set里处理一下和当前区间有交的区间,用线段树维护一下区间修改即可

至于复杂度,由于一段区间最多会被删除一次,所以是\(O((n+q)\log n)\)

代码

include<bits/stdc++.h>
#define re register
#define LL long long
#define mp std::make_pair
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=1e5+5;
typedef std::pair<int,int> pii;
struct E{int v,nxt;}e[maxn<<1];pii st[maxn];
int n,m,head[maxn],num,sum[maxn],dfn[maxn],top,__;
inline void add_(int x,int y){e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
struct Segment_Tree {
    int l[maxn<<2],r[maxn<<2],tag[maxn<<2];LL d[maxn<<2];
    inline void pushr(int i,int v) {d[i]+=1ll*v*(r[i]-l[i]+1);tag[i]+=v;}
    inline void pushdown(int i) {
        if(!tag[i])return;pushr(i<<1,tag[i]),pushr(i<<1|1,tag[i]);tag[i]=0;
    }
    inline void pushup(int i) {d[i]=d[i<<1]+d[i<<1|1];}
    void build(int x,int y,int i) {
        l[i]=x,r[i]=y;if(x==y)return;
        int mid=x+y>>1;build(x,mid,i<<1),build(mid+1,y,i<<1|1);
    }
    void add(int x,int y,int v,int i) {
        if(x<=l[i]&&y>=r[i]) {pushr(i,v);return;}
        int mid=l[i]+r[i]>>1;pushdown(i);
        if(x<=mid)add(x,y,v,i<<1);if(y>mid)add(x,y,v,i<<1|1);pushup(i);
    }
    LL query(int x,int y,int i) {
        if(x<=l[i]&&y>=r[i]) return d[i];
        int mid=l[i]+r[i]>>1;pushdown(i);
        return (x<=mid?query(x,y,i<<1):0)+(y>mid?query(x,y,i<<1|1):0);
    }
}T;
struct Set {
    std::set<pii> s;
    #define fl first
    #define fr second
    std::set<pii>::iterator it;
    inline void ins(int l,int r) {
        top=0;it=s.lower_bound(mp(l,0));
        if(it!=s.begin()) --it; 
        for(;it!=s.end();++it) {
            pii k=(*it);if(k.fr<l) continue;
            if(k.fl>r) break;
            st[++top]=k;T.add(k.fl,k.fr,-1,1);
        }
        if(!top) {
            s.insert(mp(l,r));T.add(l,r,1,1);return;
        }
        for(re int i=1;i<=top;i++) s.erase(st[i]);
        int L=l,R=r;if(st[1].fl<L) L=st[1].fl;if(st[top].fr>R) R=st[top].fr;
        s.insert(mp(L,R)),T.add(L,R,1,1);
    }
}seg[maxn];
void dfs(int x) {
    dfn[x]=++__;sum[x]=1;
    for(re int i=head[x];i;i=e[i].nxt)
        if(!dfn[e[i].v]) dfs(e[i].v),sum[x]+=sum[e[i].v];
}
int main() {
    n=read(),m=read();
    for(re int x,y,i=1;i<n;i++) x=read(),y=read(),add_(x,y),add_(y,x);
    dfs(1);T.build(1,n,1);int op,x,c;
    while(m--) {
        op=read(),x=read();
        if(op==1) c=read(),seg[c].ins(dfn[x],dfn[x]+sum[x]-1);
        if(op==2) printf("%lld\n",T.query(dfn[x],dfn[x]+sum[x]-1,1));
    }return 0;
}

猜你喜欢

转载自www.cnblogs.com/asuldb/p/12112401.html