• 【考试总结】20220325


    异或矩阵

    使用 库默尔定理 发现,如果 \(y-x\subseteq k-1\) 那么 \((1,y)\) 将向 \((k,x)\) 造成贡献

    考虑当 \(k=2^x\) 时转移只有两个地方是子集,那么分 \(\log\) 步迭代完成转移即可

    Code Display
    const int N=3e6+10;
    unsigned int a[N],f[N];
    int n,k;
    signed main(){
        freopen("matrix.in","r",stdin); freopen("matrix.out","w",stdout);
        n=read(); k=read(); a[1]=read<ui>();
        for(int i=2;i<=n;++i) a[i]=1145141*a[i-1]+(ui)1919*i+810;
        for(int i=0;i<23;++i) if((k-1)>>i&1){
            for(int j=1;j+(1<<i)<=n;++j) a[j]^=a[j+(1<<i)]; 
        }
        ui ans=0;
        for(int i=1;i<=n-k+1;++i) ans=ans+i*(a[i]^i);
        print(ans);
        return 0;
    }
    

    点集 \(\rm LCA\) 是子树的根等价于从不少于 \(2\) 个子树里面选点或者选择它本身

    使用容斥原理即可

    感觉 xzh 同学这种明显的恶意不取模行为是十分强大的

    Code Display
    const int N=1e5+10;
    int siz[N],ans[N],n;
    vector<int> G[N];
    inline void dfs(int x,int fat){
        siz[x]=1; ans[x]=mod-1;
        for(auto t:G[x]) if(t!=fat){
            dfs(t,x); siz[x]+=siz[t];
            ckdel(ans[x],del(ksm(2,siz[t]),1));
        }
        ckadd(ans[x],ksm(2,siz[x]));
    }
    signed main(){
        freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
        n=read();
        for(int i=1;i<n;++i){
            int u=read(),v=read();
            G[u].emplace_back(v);
            G[v].emplace_back(u);
        }
        dfs(1,0);
        for(int i=1;i<=n;++i) print(ans[i]);
        return 0;
    }
    

    黑白树

    考虑线段树历史有条件最值的一种计算方式:在 push_down 时如果满足条件再转移到两个子区间里面,push_up 时如果子区间和母区间的条件一致再进行信息的维护

    那么本题中的 “条件” 就是两个点处在同色联通块中,而判定条件就是 两个点颜色相同 并且 根链上的异色点数量 相同

    将每个同色联通块的信息都挂到联通块中深度最小的点上面,求得这个点具体是谁可以使用 重链剖分 配合 std::set 来实现找到根链上第一个异色点再跳儿子即可

    将线段树上某个区间管辖点视作其所有点的 \(\rm LCA\),维护如下信息:

    • cnt[0/1] 表示两个颜色点数

    • Mx[0/1] 表示两种颜色联通块中的最值

    • cnt_tag[0/1],col_tag[0/1],tag 分别表示三种懒标记:点数修改,同色权值加,子树/链 加

    在进行区间修改的时候先查询联通块最浅点的 cnt 信息,再对其进行子树加即可,注意 \(\rm DFS\) 序区间上不满足 cnt 值相同的区间不能放懒标记

    实现的时候注意维护当前信息需要的是哪种颜色以及 push_down 时信息下放的顺序:异色点数要在同色联通块加之前来保证正确性

    Code Display
    const int N=2e5+10,inf=0x3f3f3f3f3f3f3f3f;
    int dfn[N],ord[N],top[N],son[N],siz[N],dep[N],fa[N],tim;
    vector<int> G[N];
    int n,Q,col[N];
    inline void dfs1(int x,int fat){
        dep[x]=dep[fa[x]=fat]+(siz[x]=1);
        for(auto t:G[x]) if(t!=fat){
            dfs1(t,x); siz[x]+=siz[t];
            if(siz[son[x]]<siz[t]) son[x]=t;
        } return ;
    }
    inline void dfs2(int x,int topf){
        top[x]=topf; ord[dfn[x]=++tim]=x; if(son[x]) dfs2(son[x],topf);
        for(auto t:G[x]) if(!dfn[t]) dfs2(t,t);
    }
    struct Seg{
        #define ls p<<1
        #define rs p<<1|1
        #define lson p<<1,l,mid
        #define rson p<<1|1,mid+1,r
        int add_tag[N<<2],col_tag[N<<2][2],Mx[N<<2][2];
        int cnt[N<<2][2],cnt_tag[N<<2][2];
        inline void push_cnt(int x,int c,int v){cnt_tag[x][c]+=v; cnt[x][c]+=v;}
        inline void push_add(int x,int v){add_tag[x]+=v; Mx[x][0]+=v; Mx[x][1]+=v;}
        inline void push_col(int x,int c,int v){col_tag[x][c]+=v; Mx[x][c]+=v;}
        inline void push_down(int p){
            if(add_tag[p]){
                push_add(ls,add_tag[p]);
                push_add(rs,add_tag[p]);
                add_tag[p]=0;
            }
            for(int c=0;c<=1;++c) if(cnt_tag[p][c]){
                push_cnt(ls,c,cnt_tag[p][c]);
                push_cnt(rs,c,cnt_tag[p][c]);
                cnt_tag[p][c]=0;
            }
            for(int c=0;c<=1;++c) if(col_tag[p][c]){
                if(cnt[ls][c^1]==cnt[p][c^1]) push_col(ls,c,col_tag[p][c]);
                if(cnt[rs][c^1]==cnt[p][c^1]) push_col(rs,c,col_tag[p][c]);
                col_tag[p][c]=0;
            }
            return ;
        }
        inline void push_up(int p){
            Mx[p][0]=Mx[p][1]=-inf;
            rep(c,0,1){
                if(cnt[p][c]==cnt[ls][c]) ckmax(Mx[p][c^1],Mx[ls][c^1]);
                if(cnt[p][c]==cnt[rs][c]) ckmax(Mx[p][c^1],Mx[rs][c^1]);
            } return ;
        }
        inline int query_cnt(int pos,int c,int p=1,int l=1,int r=n){
            if(l==r) return cnt[p][c];
            int mid=(l+r)>>1; push_down(p);
            if(pos<=mid) return query_cnt(pos,c,lson);
            else return query_cnt(pos,c,rson);
        } // 查询一个点根链上异色点个数
        inline int query_max(int st,int ed,int c,int num,int p=1,int l=1,int r=n){
            if(cnt[p][c^1]>num) return -inf;
            if(st<=l&&r<=ed) return Mx[p][c];
            int mid=(l+r)>>1,res=0; push_down(p);
            if(st<=mid) ckmax(res,query_max(st,ed,c,num,lson));
            if(ed>mid) ckmax(res,query_max(st,ed,c,num,rson));
            return res;
        } // 查询同一个联通块的最大值
        inline void cnt_add(int st,int ed,int c,int v,int p=1,int l=1,int r=n){
            if(st<=l&&r<=ed) return push_cnt(p,c,v);
            int mid=(l+r)>>1; push_down(p);
            if(st<=mid) cnt_add(st,ed,c,v,lson);
            if(ed>mid) cnt_add(st,ed,c,v,rson);
            return push_up(p);
        } // 更改异色点个数
        inline void give_add(int st,int ed,int v,int p=1,int l=1,int r=n){
            if(st<=l&&r<=ed) return push_add(p,v);
            int mid=(l+r)>>1; push_down(p);
            if(st<=mid) give_add(st,ed,v,lson);
            if(ed>mid) give_add(st,ed,v,rson);
            return push_up(p);
        } // 链加,子树加
        inline void col_add(int st,int ed,int c,int num,int v,int p=1,int l=1,int r=n){
            if(cnt[p][c^1]>num) return ;
            if(st<=l&&r<=ed) return push_col(p,c,v);
            int mid=(l+r)>>1; push_down(p);
            if(st<=mid) col_add(st,ed,c,num,v,lson);
            if(ed>mid) col_add(st,ed,c,num,v,rson);
            return push_up(p);
        } // 联通块加
        inline void change_col(int pos,int p=1,int l=1,int r=n){
            if(l==r) return swap(Mx[p][0],Mx[p][1]);
            int mid=(l+r)>>1; push_down(p);
            if(pos<=mid) change_col(pos,lson);
            else change_col(pos,rson);
            return push_up(p);
        }
    }T;
    set<pair<int,int> > st[2][N];
    inline int find(int x){
        int c=col[x]^1,ans=x;
        for(;x;x=fa[top[x]]){
            auto t=st[c][top[x]].upper_bound(make_pair(dep[x],inf));
            if(t!=st[c][top[x]].begin()){
                --t;
                if(t->sec==x) return ans;
                else return son[t->sec];
            }else ans=top[x];
        } return ans;
    }
    signed main(){
        freopen("astill.in","r",stdin); freopen("astill.out","w",stdout);
        n=read(); Q=read();
        for(int i=1;i<n;++i){
            int u=read(),v=read();
            G[u].emplace_back(v);
            G[v].emplace_back(u);
        }
        dfs1(1,0); dfs2(1,1);
        rep(i,1,n){
            st[col[i]=read()][top[i]].insert({dep[i],i});
            T.cnt_add(dfn[i],dfn[i]+siz[i]-1,col[i],1);
        }
        rep(i,1,n) T.give_add(dfn[i],dfn[i],read());
        while(Q--){
            int opt=read();
            if(opt==1){
                int x=read();
                st[col[x]][top[x]].erase(make_pair(dep[x],x));
                T.cnt_add(dfn[x],dfn[x]+siz[x]-1,col[x],-1);
                col[x]^=1;
                st[col[x]][top[x]].insert(make_pair(dep[x],x));
                T.change_col(dfn[x]);
                T.cnt_add(dfn[x],dfn[x]+siz[x]-1,col[x],1);
            }else if(opt==2){
                int x=find(read()),v=read();
                T.col_add(dfn[x],dfn[x]+siz[x]-1,col[x],T.query_cnt(dfn[x],1^col[x]),v);
            }else if(opt==3){
                int x=find(read());
                print(T.query_max(dfn[x],dfn[x]+siz[x]-1,col[x],T.query_cnt(dfn[x],col[x]^1)));
            }else if(opt==4){
                int x=read(),y=read(),v=read();
                while(top[x]!=top[y]){
                    if(dep[top[x]]<dep[top[y]]) swap(x,y);
                    T.give_add(dfn[top[x]],dfn[x],v);
                    x=fa[top[x]];
                }
                if(dep[x]>dep[y]) swap(x,y);
                T.give_add(dfn[x],dfn[y],v);
            }else if(opt==5){
                int x=read(),v=read();
                T.give_add(dfn[x],dfn[x]+siz[x]-1,v);   
            }
        }
        return 0;
    }
    

  • 相关阅读:
    535. Encode and Decode TinyURL 长短URL
    190. Reverse Bits 二进制相反数
    476. Number Complement 二进制中的相反对应数
    598. Range Addition II 矩阵的范围叠加
    507. Perfect Number 因数求和
    asp.net core 系列之用户认证(1)-给项目添加 Identity
    asp.net core 系列之用户认证(authentication)
    asp.net core 系列之webapi集成Dapper的简单操作教程
    asp.net core 系列之webapi集成EFCore的简单操作教程
    asp.net core 系列之中间件基础篇(middleware)
  • 原文地址:https://www.cnblogs.com/yspm/p/16056632.html
Copyright © 2020-2023  润新知