zoukankan      html  css  js  c++  java
  • 牛客网NOIP提高组模拟赛第六场C树solution

    纪念一下目前写的最长的代码—5.66KB
    本题就是巨型数据结构题,用树剖加线段树维护一下父亲边与儿子边的修改,换根分类讨论一下即可
    直接上代码:
    #include<cstdio>
    #include<iostream>
    namespace fast_IO {
    const int IN_LEN=10000000,OUT_LEN=10000000;
    char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf;
    char *lastin=ibuf+IN_LEN; const char *lastout=ibuf+OUT_LEN-1;
    inline char getchar_() { if(ih==lastin)lastin=ibuf+fread(ibuf,1,IN_LEN,stdin),ih=ibuf; return (*ih++); }
    inline void putchar_(const char x) { if(ih==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf; *oh++=x; }
    inline void flush(){fwrite(obuf, 1, oh - obuf, stdout);} }
    using namespace fast_IO;
    #define getchar() getchar_()
    #define putchar(x) putchar_((x))
    inline int read(){int x=0;char cu=getchar();x=0;while(!isdigit(cu))cu=getchar(); while(isdigit(cu))x=x*10+cu-'0',cu=getchar();return x;}
    template <typename T> void print(const T x){if(x>=10)print(x/10); putchar(x%10+'0'); }
    using namespace std;
    const int N=1e5+10;
    int n,m,A,B,head[N],cnt,son[N],hson[N],depth[N],f[N],pre[N],las[N],cl,top[N],opt,x,y,col,colk,num;
    struct edge{int nxt,to;}ed[N<<1];
    struct data{int col,t;}t1,t2;
    struct Segment_Tree{int sum[3];data tag,son;}seg[N<<2];
    inline void addedge(int x,int y){
        ed[++cnt].to=y;ed[cnt].nxt=head[x];head[x]=cnt;
        ed[++cnt].to=x;ed[cnt].nxt=head[y];head[y]=cnt;}
    inline void DFS1(int u,int fa,int de){
        depth[u]=de;f[u]=fa;son[u]=1;
        for(register int i=head[u];i;i=ed[i].nxt){
            int v=ed[i].to;if(v==fa)continue;
            DFS1(v,u,de+1);if(son[hson[u]]<son[v])hson[u]=v;son[u]+=son[v];}
    }
    inline void DFS2(int u,int heavy){
        pre[u]=++cl;top[u]=heavy;if(hson[u])DFS2(hson[u],heavy);
        for(register int i=head[u];i;i=ed[i].nxt){
            int v=ed[i].to;if(v==f[u]||v==hson[u])continue;DFS2(v,v);}
        las[u]=cl;
    }
    inline void build(int o,int L,int R){
        if(L==R){seg[o].tag=(data){0,0};seg[o].sum[0]=1;return;}
        int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;build(lc,L,M);build(rc,M+1,R);
        seg[o].sum[0]=seg[lc].sum[0]+seg[rc].sum[0];seg[o].tag=seg[o].son=(data){-1,-1};
    }
    inline void pushdown(int o,int L,int R){
        if(seg[o].tag.col!=-1&&seg[o].tag.t!=-1){
            int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;
            seg[lc].tag=seg[o].tag;seg[rc].tag=seg[o].tag;
            for(register int i=0;i<=2;i++)
                if(i==seg[o].tag.col)seg[lc].sum[i]=M-L+1;
                else seg[lc].sum[i]=0;
            for(register int i=0;i<=2;i++)
                if(i==seg[o].tag.col)seg[rc].sum[i]=R-M;
                else seg[rc].sum[i]=0;
            seg[o].tag=(data){-1,-1};
        }
        if(seg[o].son.col!=-1&&seg[o].son.t!=-1){
            int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;
            seg[lc].son=seg[o].son;seg[rc].son=seg[o].son;
            seg[o].son=(data){-1,-1};
        }
    }
    inline int Query(int o,int L,int R,int l,int r,int v){
        if(l<=L&&R<=r)return seg[o].sum[v];int sum=0;
        pushdown(o,L,R);int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;
        if(l<=M)sum+=Query(lc,L,M,l,r,v);if(r>M)sum+=Query(rc,M+1,R,l,r,v);
        return sum;}
    inline data&Find(int o,int L,int R,int x,int op){
        if(L==R){if(op)return seg[o].tag;else return seg[o].son;}
        pushdown(o,L,R);int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;
        if(x<=M)return Find(lc,L,M,x,op);else return Find(rc,M+1,R,x,op);
    }
    inline int query(int u,int v,int col){
        int ans=0;
        while(top[u]!=top[v]){
            if(depth[top[u]]<depth[top[v]])swap(u,v);
            if(pre[top[u]]+1<=pre[u])ans+=Query(1,1,n,pre[top[u]]+1,pre[u],col);
            data k1=Find(1,1,n,pre[top[u]],1),k2;
            if(pre[f[top[u]]])k2=Find(1,1,n,pre[f[top[u]]],0);else k2=(data){-1,-1};
            if(k2.t==-1||k1.t>=k2.t)ans+=(k1.col==col);else ans+=(k2.col==col);
            //k1.t==k2.t的时候算是k1后更新,取k1的颜色,因为链更新时将一条链上的son与tag一同更新,这样会导致son和tag的时间戳相同,然而实际上链上的点并不会受son的影响,它们的data依然是tag
            u=f[top[u]];
        }
        if(depth[u]<depth[v])swap(u,v);
        if(pre[v]+1<=pre[u])ans+=Query(1,1,n,pre[v]+1,pre[u],col);
        return ans;
    }
    inline void updata(int o,int L,int R,int l,int r,int op,data v){
        if(l<=L&&R<=r){
            if(op)seg[o].son=v;
            else{seg[o].tag=v;for(register int i=0;i<=2;i++)if(v.col==i)seg[o].sum[i]=R-L+1;else seg[o].sum[i]=0;}
            return;
        }
        pushdown(o,L,R);int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;
        if(l<=M)updata(lc,L,M,l,r,op,v);if(r>M)updata(rc,M+1,R,l,r,op,v);
        for(register int i=0;i<=2;i++)seg[o].sum[i]=seg[lc].sum[i]+seg[rc].sum[i];
    }
    inline void update(int u,int v,int col1,int col2){
        num++;t1=(data){col1,num};t2=(data){col2,num};
        while(top[u]!=top[v]){
            if(depth[top[u]]<depth[top[v]])swap(u,v);
            updata(1,1,n,pre[top[u]],pre[u],0,t1);
            updata(1,1,n,pre[top[u]],pre[u],1,t2);
            if(hson[u])updata(1,1,n,pre[u]+1,pre[u]+1,0,t2);
            u=f[top[u]];
        }
        if(depth[u]<depth[v])swap(u,v);
        if(pre[v]+1<=pre[u])updata(1,1,n,pre[v]+1,pre[u],0,t1);
        updata(1,1,n,pre[v],pre[u],1,t2);
        if(hson[u])updata(1,1,n,pre[u]+1,pre[u]+1,0,t2);
        updata(1,1,n,pre[v],pre[v],0,t2);
    }
    inline int Jump(int u,int goal){
        int w;
        if(depth[u]<depth[goal])return -1;
        while(top[u]!=top[goal]){
            if(depth[top[u]]<depth[top[goal]])return -1;w=top[u];u=f[top[u]];}
        if(depth[u]<depth[goal])return -1;
        if(u==goal)return w;else return hson[goal];
    }
    int main(){
        n=read();
        for(register int i=1;i<n;i++)A=read(),B=read(),addedge(A,B);
        DFS1(1,0,1);DFS2(1,1);build(1,1,n);
        m=read();
        while(m--){
            opt=read();x=read();y=read();col=read();
            if(opt==2)colk=read();
            if(opt==1)printf("%d\n",query(x,y,col));
            if(opt==2)update(x,y,col,colk);
            if(opt==3){
                num++;t1=(data){col,num};
                if(x==y)updata(1,1,n,1,n,0,t1);
                else{
                    int k=Jump(x,y);
                    if(k==-1)updata(1,1,n,pre[y]+1,las[y],0,t1);
                    else{
                        if(1<=pre[k]-1)updata(1,1,n,1,pre[k]-1,0,t1);
                        if(las[k]+1<=n)updata(1,1,n,las[k]+1,n,0,t1);}
                }
            }
        }
        flush();return 0;
    }
    
  • 相关阅读:
    剑指05两个栈实现一个队列
    11 幂等 Idempotence
    13 SOAP
    leetcode143zigzag-conversion
    如何使用 awk 复合表达式
    IT 运行在云端,而云运行在 Linux 上
    Docker1.12 + Swarm 构建动态微服务应用
    教你在Ubuntu上体验Mac风格
    Zabbix-3.0.3结合Grafana-3.1.0给你想要的绘图
    Zabbix-3.0.3使用自带模板监控MySQL
  • 原文地址:https://www.cnblogs.com/ForwardFuture/p/9845227.html
Copyright © 2011-2022 走看看