zoukankan      html  css  js  c++  java
  • Codeforces Round #520 (Div. 2)

    D. Fun with Integers
    题意:
    给你一个n,对于任意的 2|a|,|b|n ,如果存在一个整数x,使得 $a*x=b$ 或者 $b*x=a$ ,那么a向b连一条边权为|x|的边。
    问不经过重复的边最长的一条路径的长度。
    思路:
    我们发现这张图有欧拉回路,然后就把所有边权加起来就好了2333333
    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,ans;
    signed main(){
        scanf("%lld",&n);
        for(int i=2;i<=n;i++)
            for(int j=i*2;j<=n;j+=i)
                ans+=j/i;
        printf("%lld
    ",ans*4);
    }

    E. Company

    题意:

    给你一个含n个点的有根树,q次询问,每次问[l,r]区间中删掉任何一个点,使得所有点的deep[LCA]最大,问删掉的点是哪个,深度最大是多少。SPJ

    思路:

    我们可以发现,一段区间的LCA也就是dfs序最小的点和dfs序最大的点的lca。

    那我们可以枚举删除的是dfs序最小的那个点还是dfs序最大的那个点。

    具体来说就是线段树维护区间dfs序的最小值,次小值,最大值,次大值。每回询问的时候查询一下lca就好了

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int N=200050;
    int n,q,fa[N][20],v[N],nxt[N],first[N],tot,dfn[N],rev[N],cnt,deep[N];
    int maxx[N<<2],max2[N<<2],minn[N<<2],min2[N<<2];
    void add(int x,int y){
        v[tot]=y,nxt[tot]=first[x],first[x]=tot++;
    }
    
    void dfs(int x){
        dfn[x]=++cnt,rev[cnt]=x;
        for(int i=1;i<20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=first[x];~i;i=nxt[i])
            deep[v[i]]=deep[x]+1,dfs(v[i]);
    }
    
    void push_up(int pos){
        int lson=pos<<1,rson=pos<<1|1,tmp[4];
        tmp[0]=maxx[lson],tmp[1]=max2[lson];
        tmp[2]=maxx[rson],tmp[3]=max2[rson];
        sort(tmp,tmp+4);
        maxx[pos]=tmp[3],max2[pos]=tmp[2];
        tmp[0]=minn[lson],tmp[1]=min2[lson];
        tmp[2]=minn[rson],tmp[3]=min2[rson];
        sort(tmp,tmp+4);
        minn[pos]=tmp[0],min2[pos]=tmp[1];
    }
    
    void build(int l,int r,int pos){
        if(l==r){
            maxx[pos]=minn[pos]=dfn[l];
            min2[pos]=N;
            return;
        }
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        build(l,mid,lson),build(mid+1,r,rson);
        push_up(pos);
    }
    
    pair<int,int> query_max(int l,int r,int pos,int L,int R){
        if(l>=L&&r<=R)return make_pair(maxx[pos],max2[pos]);
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        if(mid<L)return query_max(mid+1,r,rson,L,R);
        else if(mid>=R)return query_max(l,mid,lson,L,R);
        else{
            pair<int,int>t=query_max(l,mid,lson,L,R);
            pair<int,int>t2=query_max(mid+1,r,rson,L,R);
            int tmp[4];
            tmp[0]=t.first,tmp[1]=t.second;
            tmp[2]=t2.first,tmp[3]=t2.second;
            sort(tmp,tmp+4);
            return make_pair(tmp[3],tmp[2]);
        }
    }
    
    pair<int,int> query_min(int l,int r,int pos,int L,int R){
        if(l>=L&&r<=R)return make_pair(minn[pos],min2[pos]);
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        if(mid<L)return query_min(mid+1,r,rson,L,R);
        else if(mid>=R)return query_min(l,mid,lson,L,R);
        else{
            pair<int,int>t=query_min(l,mid,lson,L,R);
            pair<int,int>t2=query_min(mid+1,r,rson,L,R);
            int tmp[4];
            tmp[0]=t.first,tmp[1]=t.second;
            tmp[2]=t2.first,tmp[3]=t2.second;
            sort(tmp,tmp+4);
            return make_pair(tmp[0],tmp[1]);
        }
    }
    
    int lca(int x,int y){
        if(x<1||x>n)return -1;
        if(deep[x]<deep[y])swap(x,y);
        for(int i=19;~i;i--)if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
        if(x==y)return x;
        for(int i=19;~i;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    
    int main(){
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&q);
        for(int i=2;i<=n;i++)scanf("%d",&fa[i][0]),add(fa[i][0],i);
        dfs(1);build(1,n,1);
        while(q--){
            int xx,yy;
            scanf("%d%d",&xx,&yy);
            pair<int,int>mx=query_max(1,n,1,xx,yy);
            pair<int,int>mn=query_min(1,n,1,xx,yy);
            int t1=lca(rev[mx.first],rev[mn.second]);
            int t2=lca(rev[mx.second],rev[mn.first]);
            if(deep[t1]>=deep[t2])printf("%d %d
    ",rev[mn.first],deep[t1]);
            else printf("%d %d
    ",rev[mx.first],deep[t2]);
        }
    }

    F.

    题意:

    给你一个DAG。

    对于每个点,我们需要统计两个量:

    从它出发能到的点的数量a

    从其它点出发能到达它的点的数量b

    如果a+b=n-2,那么这个点是好的

    问这张图里有多少个好的点

    思路:

    一开始没有思路,参考了题解

    我们可以拓扑排序一下,有三种情况

    1.拓扑排序的过程中队列大小为0,也就是只有一条链,那么这个点贡献+=还没有进入队列的所有点

    2.如果队列大小为1,也就是有两条链,这个时候需要判断一下另一个点所到达的所有点的入读是不是都>1,如果有不是的,那么就不管。

    如果都>1,当前点贡献+=还没有进入队列的点

    3.如果队列大小>1,那么这个点不可能满足条件

    反向建图再来一遍

    如果两次贡献和+2>=n,那么这个点是好的

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int N=600050;
    int n,m,fm[N],to[N],in[N],all,ans[N],e;
    vector<int>g[N];queue<int>q;
    void topsort(int *u,int *v){
        memset(in,0,sizeof(in)),all=n;
        for(int i=1;i<=n;i++)g[i].clear();
        while(!q.empty())q.pop();
        for(int i=1;i<=m;i++)g[u[i]].push_back(v[i]),in[v[i]]++;
        for(int i=1;i<=n;i++)if(!in[i])q.push(i),all--;
        while(!q.empty()){
            int t=q.front();q.pop();
            if(q.empty())ans[t]+=all;
            else if(q.size()==1){
                bool flg=1;
                for(auto i:g[q.front()])flg&=(in[i]>1);
                ans[t]+=flg*all;
            }
            else ans[t]=-N;
            for(auto i:g[t])if(!(--in[i]))q.push(i),all--;
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&fm[i],&to[i]);
        topsort(fm,to),topsort(to,fm);
        for(int i=1;i<=n;i++)if(ans[i]+2>=n)e++;
        printf("%d
    ",e);
    }
  • 相关阅读:
    Yii2 的 updateAll 方法参数详解
    Yii2 数据库查询汇总
    Git常见报错
    git rebase篇
    在 Yii 2.0 上,使用 updateAll() 更新表列值为同一表的另一列值的实现
    Git从其他分支merge个别文件
    Git cherry-pick 复制多个commit
    Git 删除某次提交(某个commit)的方法
    多进程记录
    python3安装Crypto过程
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/10009636.html
Copyright © 2011-2022 走看看