【考试总结】2022-03-18


无向图

问题是 \(S\) 形成的线性空间维度数量,使用可删除线性基来实现即可

一种做法是线段树分治

Code Display
int m,Q;
struct Linear_Basis{
    int b[40]; Linear_Basis(){memset(b,0,sizeof(b));}
    inline void insert(int x){
        for(int i=m;i>=1;--i) if(x>>(i-1)&1){
            if(!b[i]) return b[i]=x,void();
            else x^=b[i];
        } return ;
    }
    inline int solve(){
        int cnt=0;
        for(int i=1;i<=m;++i){
            cnt+=(bool)b[i];
        } return 1ll< ele[N<<2];
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
inline void upd(int st,int ed,int v,int p=1,int l=1,int r=Q){
    if(st<=l&&r<=ed)return ele[p].push_back(v),void();
    int mid=(l+r)>>1;
    if(st<=mid) upd(st,ed,v,lson); if(ed>mid) upd(st,ed,v,rson);
    return ;
}
inline void solve(int p,int l,int r,Linear_Basis now){
    for(auto v:ele[p]) now.insert(v);
    if(l==r) return print(now.solve());
    int mid=(l+r)>>1;
    solve(lson,now); solve(rson,now);
    return ;
}
#undef lson
#undef rson
map mp;
signed main(){
    freopen("xor.in","r",stdin); freopen("xor.out","w",stdout);
    m=read(); Q=read();
    for(int i=1;i<=Q;++i){
        int opt=read();
        int x=read();
        if(opt==1) mp[x]=i;
        else upd(mp[x],i-1,x),mp.erase(x);
    }
    for(auto t:mp) upd(t.sec,Q,t.fir);
    Linear_Basis tmp;
    solve(1,1,Q,tmp);
    return 0;
}

加与乘

考虑到如果 \(A\) 最后一次操作那么一定赢,否则如果 \(B\) 最后一次操作的时候没有奇数那么也会输

所以问题可以表达作 \(A\) 最少使用多少次操作可以让序列里面没有 \(1\)

注意在删掉两个奇数这个过程中一定 \(B\) 一定能找得到偶数把它删掉,如果全是奇数 \(A\) 删掉一个逼迫 \(B\) 删奇数和直接删两个效率一样

Code Display
signed main(){
    freopen("game.in","r",stdin); freopen("game.out","w",stdout);
    int T=read(); while(T--){
        int n,opt;
        n=read(); opt=read();
        vector vec(n);
        rep(i,0,n-1) vec[i]=read()&1;
        if((n&1)==opt) cout<<"A"<(n-1)/2) puts("B");
            else puts("A");
        }
    }   
    return 0;
}

数颜色

考虑前两天做的经典容斥:一条链上点数 \(-\) 边数 \(=1\),所以将不经过父边的 \(\rm LCA\) 拿出来

使用主席树计算前缀每个点被覆盖次数,配合以二分可以算出来这个 \(\rm LCA\) 作为联通块深度最小点的区间,相同 \(\rm LCA\) 找最后一个即可

得到贡献区间之后使用 \(\text{Fenwick Tree}\) 即可

Code Display
const int N=1e5+10;
int n,m,Q,x[N],y[N];
vector G[N];
int fa[N],son[N],dep[N],siz[N],top[N],dfn[N],tim;
inline void dfs1(int x,int y){
    dep[x]=dep[fa[x]=y]+(siz[x]=1);
    for(int t:G[x]) if(t!=y){
        dfs1(t,x); siz[x]+=siz[t];
        if(siz[t]>siz[son[x]]) son[x]=t;
    } return ;
}
inline void dfs2(int x,int topf){
    top[x]=topf; dfn[x]=++tim; if(son[x]) dfs2(son[x],topf);
    for(auto t:G[x]) if(!dfn[t]) dfs2(t,t);
    return ;
}
inline int get_lca(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]] >qu[N];
vector >vals[N];
const int M=N*300;
int Tim,tot,rt[N],ls[M],rs[M],tag[M];
inline void upd(int &p,int pre,int l,int r,int st,int ed){    
    if(p<=Tim) p=++tot,ls[p]=ls[pre],rs[p]=rs[pre],tag[p]=tag[pre];
    if(st<=l&&r<=ed) return tag[p]++,void();
    int mid=(l+r)>>1;
    if(st<=mid) upd(ls[p],ls[pre],l,mid,st,ed);
    if(ed>mid) upd(rs[p],rs[pre],mid+1,r,st,ed);
    return ;
}
inline int query(int p,int l,int r,int pos){
    if(!p) return 0;
    if(l==r) return tag[p]; int mid=(l+r)>>1;
    if(pos<=mid) return query(ls[p],l,mid,pos)+tag[p];
    else return query(rs[p],mid+1,r,pos)+tag[p];
}
int lca[N];
inline void push_path(int id,int x,int y){
    rt[id]=rt[id-1]; Tim=tot;
    lca[id]=get_lca(x,y);
    while(top[x]!=top[lca[id]]){
        upd(rt[id],rt[id],1,n,dfn[top[x]],dfn[x]);
        x=fa[top[x]];
    }
    while(top[y]!=top[lca[id]]){
        upd(rt[id],rt[id],1,n,dfn[top[y]],dfn[y]);
        y=fa[top[y]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    if(x!=y) upd(rt[id],rt[id],1,n,dfn[x]+1,dfn[y]);
    return ;
}
int pre[N],nxt[N],lst[N];
signed main(){
    freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
    n=read(); m=read(); Q=read();
    for(int i=1;i>1;
            if(query(rt[mid],1,n,dfn[lca[i]])==query(rt[i],1,n,dfn[lca[i]])) rig=mid-1,ans=mid;
            else lef=mid+1;
        }
        int pos=ans+1;
        vals[i].emplace_back(pos,i,1);
        lef=i+1,rig=m; ans=m+1;
        while(lef<=rig){
            int mid=(lef+rig)>>1;
            if(query(rt[mid],1,n,dfn[lca[i]])==query(rt[i],1,n,dfn[lca[i]])) lef=mid+1;
            else rig=mid-1,ans=mid;
        }
        vals[min(nxt[i],ans)].emplace_back(pos,i,-1);
    }
    for(int i=1;i<=Q;++i){
        int l=read(),r=read();
        qu[r].emplace_back(l,i);
    }
    for(int i=1;i<=m;++i){
        for(auto t:vals[i]){
            int a,b,c; tie(a,b,c)=t;
            T.insert(a,c);
            T.insert(b+1,-c);
        }
        for(auto q:qu[i]) ans[q.sec]=T.query(q.fir);
    }
    for(int i=1;i<=Q;++i) print(ans[i]);
    return 0;
}

感觉这套题在联赛前考和在现在考多数同学的得分并不会有什么不同