• 20190312


    第一次打字竞赛QwQ

    T1

    内存限制:512 MiB
    时间限制:1000 ms
    由于 zzq 太懒了,所以这题没有题目背景。
    有一棵树,树上有 $n$ 个点,每条边上有一个非负边权。
    在这 $n$ 个点中有 $k$ 个特殊点,其中 $k$ 为偶数。定义两个点的距离为它们在树上的简单路径上的边权之和。你需要将这 $k$ 个点配成 $frac{k}{2}$ 个互不相交的对,并最大化每一对点的距离之和。
    $1 leq n,c leq 10^5$

    题解

    最终所有的路径会交于一点,如果没有交于一点的话,交于一点更优
    所以只要一个点,如果以这个点为根,最大的子树内含有的配对点数 $leq frac{k}{2}$ ,则以这个点为根去配对即可

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    int n,k,hd[N],nx[N*2],t,V[N*2],sz[N],ax[N],now;
    bool vis[N];stack<int>g[N];
    struct O{
        int x,s;
        friend bool operator < (const O& A,const O& B){
            return A.s<B.s;
        }
    };
    priority_queue<O>q;
    void add(int u,int v){
        V[++t]=v;nx[t]=hd[u];hd[u]=t;
    }
    void get(int x,int fa){
        if (vis[x]) g[now].push(x);
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fa) get(V[i],x);
    }
    void dfs(int x,int fa){
        sz[x]=vis[x];
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fa)
                dfs(V[i],x),sz[x]+=sz[V[i]],
                ax[x]=max(ax[x],sz[V[i]]);
        ax[x]=max(ax[x],k-sz[x]);
        if ((ax[x]<<1)<=k){
            for (int i=hd[x];i;i=nx[i]){
                now=V[i],get(V[i],x);
                int s=g[V[i]].size();
                if (s) q.push(O{V[i],s});
            }
            if (vis[x])
                g[x].push(x),q.push((O){x,1});
            while(!q.empty()){
                int A=q.top().x;q.pop();
                int B=q.top().x;q.pop();
                printf("%d %d
    ",g[A].top(),g[B].top());
                g[A].pop();g[B].pop();
                int sA=g[A].size(),sB=g[B].size();
                if (sA) q.push((O){A,sA});
                if (sB) q.push((O){B,sB});
            }
            exit(0);
        }
    }
    int main(){
        scanf("%d%d",&n,&k);
        for (int x,y,z,i=1;i<n;i++)
            scanf("%d%d%d",&x,&y,&z),
            add(x,y),add(y,x);
        for (int x,i=1;i<=k;i++)
            scanf("%d",&x),vis[x]=1;
        dfs(1,0);return 0;
    }

    T2

    内存限制:256 MiB
    时间限制:1000 ms
    给定字符集大小 $S$ ,问有多少个长度为 $N$ 的字符串不存在长度 $>1$ 的回文后缀。
    答案对 $M$ 取模。
    $1 leq n leq 10^7,1leq S < M leq 2^{30}-1$

    题解

    将字符串倒着看,设 $f_i$ 表示前 $i$ 位且满足条件的字符串的方案数
    则 $f_i=f_{i-1} imes s - f_{frac{i+1}{2}}$
    (前 $frac{i+1}{2}$ 不为回文,将其反过来为回文

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=1e7+5;
    LL s,m,f[N];int n;
    int main(){
        scanf("%d%lld%lld",&n,&s,&m);
        f[0]=1;for (int i=1;i<=n;i++)
            f[i]=(f[i-1]*s-f[(i+1)/2])%m;
        return printf("%lld
    ",f[n]),0;
    }

    T3

    内存限制:512 MiB
    时间限制:1000 ms
    有一棵 $n$ 个点的树,每个节点上有一个权值 $w_i$ ,最开始根为 $1$ 号点。现在有 $3$ 种类型的操作:
    · 1 $root$ , 表示将根设为 $root$ 。
    · 2 $u$ $v$ $x$ , 设 $u,v$ 的最近公共祖先为 $p$ , 将 $p$ 的子树中的所有点的权值加上 $x$ 。
    · 3 $u$ ,查询 $u$ 的子树中的所有点的权值和。
    对于每个 3 操作,输出答案。
    $1 leq n,q leq 3 imes 10^5,-10^7 leq w_i,x leq 10^7$

    题解

    没有真的换根呦
    对于 2 操作,我们可以进行一下分讨
    设 $l=lca(u,v)$

    1. $u$ 在 $root$ 子树内, $v$ 在 $root$ 子树内
      如果 $l=rt$ 就是全部 $+x$ ,否则就是 $l$ 子树 $+x$
    2. $u$ 在 $root$ 子树内, $v$ 不在 $root$ 子树内/ $u$ 不在 $root$ 子树内, $v$ 在 $root$ 子树内
      全部 $+x$
    3. $u$ 不在 $root$ 子树内, $v$ 不在 $root$ 子树内
      如果 $l$ 不为 $root$ 的祖先,就是 $l$ 子树 $+x$
      否则先全部 $+x$ ,然后找到 $root$ 到 $l$ 的路径上最后一个不在 $u$ 到 $v$ 这条路径上的点 $w$ , $w$ 子树 $+x$

    对于3 操作进行类似的分讨,即可过题

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=3e5+5;
    int rt,q,w[N],n,c,f[N*2][22],hd[N],nx[N*2],V[N*2],t,tt,id[N],dfn[N],e[N],d[N],ot[N],lg[N*2],fa[N][22];
    LL s[N*4],ans,tg[N*4];
    void add(int u,int v){
        V[++t]=v;nx[t]=hd[u];hd[u]=t;
    }
    void dfs(int x,int F){
        f[++c][0]=x;d[x]=d[F]+1;fa[x][0]=F;
        for (int i=1;fa[fa[x][i-1]][i-1];i++)
            fa[x][i]=fa[fa[x][i-1]][i-1];
        dfn[id[x]=++tt]=x;e[x]=c;
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=F)
                dfs(V[i],x),f[++c][0]=x;
        ot[x]=tt;
    }
    int lca(int l,int r){
        if (l>r) swap(l,r);int i=log2(r-l+1);
        if (d[f[l][i]]<d[f[r-(1<<i)+1][i]])
            return f[l][i];
        return f[r-(1<<i)+1][i];
    }
    bool pd(int x,int y){
        return (id[x]>=id[y] && id[x]<=ot[y]);
    }
    #define Ls k<<1
    #define Rs k<<1|1
    #define mid ((l+r)>>1)
    void pushdown(int k,int l,int r){
        LL v=tg[k];tg[k]=0;
        s[Ls]+=v*(mid-l+1);tg[Ls]+=v;
        s[Rs]+=v*(r-mid);tg[Rs]+=v;
    }
    void build(int k,int l,int r){
        if (l==r) s[k]=w[dfn[l]];
        else
            build(Ls,l,mid),
            build(Rs,mid+1,r),
        s[k]=s[Ls]+s[Rs];
    }
    void update(int k,int l,int r,int L,int R,int v){
        if (L<=l && r<=R){
            s[k]+=1ll*v*(r-l+1);tg[k]+=v;return;
        }
        if (tg[k]) pushdown(k,l,r);
        if (mid>=L) update(Ls,l,mid,L,R,v);
        if (mid<R) update(Rs,mid+1,r,L,R,v);
        s[k]=s[Ls]+s[Rs];
    }
    LL query(int k,int l,int r,int L,int R){
        if (L<=l && r<=R) return s[k];
        if (tg[k]) pushdown(k,l,r);
        if (mid<L) return query(Rs,mid+1,r,L,R);
        else if (mid>=R) return query(Ls,l,mid,L,R);
        return query(Rs,mid+1,r,L,R)+query(Ls,l,mid,L,R);
    }
    int main(){
        for (int i=0;i<20;i++) lg[1<<i]=i;
        scanf("%d%d",&n,&q);rt=1;
        for (int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        for (int x,y,i=1;i<n;i++)
            scanf("%d%d",&x,&y),add(x,y),add(y,x);
        dfs(1,0);build(1,1,n);
        for (int i=c;i;i--)
            for (int j=1;i+(1<<j)<=c+1;j++)
                if (d[f[i][j-1]]<d[f[i+(1<<(j-1))][j-1]])
                    f[i][j]=f[i][j-1];
                else f[i][j]=f[i+(1<<(j-1))][j-1];
        for (int op,u,v,l,x;q--;){
            scanf("%d",&op);
            if (op<2) scanf("%d",&rt);
            else if (op>2){
                scanf("%d",&l);
                if (pd(l,rt)){
                    if (l==rt) ans=query(1,1,n,1,n);
                    else ans=query(1,1,n,id[l],ot[l]);
                }
                else{
                    if (lca(e[l],e[rt])==l){
                        ans=query(1,1,n,1,n);
                        l=d[rt]-d[l]-1;v=rt;
                        for (;l;l-=l&-l) v=fa[v][lg[l&-l]];
                        ans-=query(1,1,n,id[v],ot[v]);
                    }
                    else ans=query(1,1,n,id[l],ot[l]);
                }
                printf("%lld
    ",ans);
            }
            else{
                scanf("%d%d%d",&u,&v,&x);
                if (pd(u,rt)){
                    if (pd(v,rt)){
                        l=lca(e[u],e[v]);
                        if (l==rt) update(1,1,n,1,n,x);
                        else update(1,1,n,id[l],ot[l],x);
                    }
                    else update(1,1,n,1,n,x);
                }
                else{
                    if (pd(v,rt)) update(1,1,n,1,n,x);
                    else{
                        l=lca(e[u],e[v]);
                        if (pd(rt,l)){
                            update(1,1,n,1,n,x);l=rt;
                            for (int i=19;~i;i--)
                                if (fa[l][i] && !pd(u,fa[l][i]) && !pd(v,fa[l][i]))
                                    l=fa[l][i];
                            update(1,1,n,id[l],ot[l],-x);
                        }
                        else update(1,1,n,id[l],ot[l],x);
                    }
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    教你OpenCV3.2.0+VS2017开发环境配置
    使用conda 与pip命令管理Python库
    【Python+OpenCV】Windows+Python3.6.0(Anaconda3)+OpenCV3.2.0安装配置
    GitHub Toturial
    C 语言多线程与锁机制
    翻译 | Placing Search in Context The Concept Revisited
    翻译 | Improving Distributional Similarity with Lessons Learned from Word Embeddings
    Derivative of Softmax Loss Function
    从头推导与实现 BP 网络
    施密特正交化 GramSchmidt
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10544779.html
Copyright © 2020-2023  润新知