【考试总结】2022-03-25


异或矩阵

使用 库默尔定理 发现,如果 \(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();
    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<

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

使用容斥原理即可

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

Code Display
const int N=1e5+10;
int siz[N],ans[N],n;
vector 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

黑白树

考虑线段树历史有条件最值的一种计算方式:在 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 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]]>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 > 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;idep[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;
}

相关