zoukankan      html  css  js  c++  java
  • 11.9模拟赛

    Problem 1 Graph (graph.cpp/c/pas)

     

    【题目描述】

    给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点。

     

    【输入格式】

    第 1 行,2 个整数 N,M。 接下来 M 行,每行 2 个整数 Ui,Vi,表示边 ⟨Ui,Vi⟩。点用 1,2,...,N 编号。

     

    【输出格式】

    N 个整数 A(1),A(2),...,A(N)。

     

    【样例输入】

    4 3

    1 2

    2 4

    4 3

    【样例输出】

    4 4 3 4

    【数据范围】

    对于 60% 的数据,1 ≤ N,K ≤ 10^3

    对于 100% 的数据,1 ≤ N,M ≤ 10^5。

    题解:

    暴力+错误tarjan缩点

    先写的缩点,对拍半天,补了n个漏洞,跑大数据平均10个WA3个

    两个程序就一起交了。略丑。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define N 100008
    using namespace std;
    int n,m,sumedge;
    queue<int>q;
    int head[N];
    
    int ans[N],vis[N];
    
    int top,tim,sumcol;
    
    int low[N],dfn[N],Stack[N],instack[N],bel[N],mx[N];
    
    int cd[N],rd[N];
    
    inline int read(){
        char ch=getchar();int x=0,f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[N];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void bfs(int x){
        memset(vis,0,sizeof(vis));
        vis[x]=true;
        while(!q.empty())q.pop();
        q.push(x);
        while(!q.empty()){
            int now=q.front();q.pop();
            ans[x]=max(ans[x],now);
            for(int i=head[now];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(!vis[v]){
                    q.push(v);vis[v]=1; 
                }
            }
        }
    }
    
    void tarjian(int x){
        low[x]=dfn[x]=++tim;
        Stack[++top]=x;instack[x]=true;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(instack[v])low[x]=min(low[x],dfn[v]);
            else if(!dfn[v]){
                tarjian(v);
                low[x]=min(low[x],low[v]);
            }
        }
        if(low[x]==dfn[x]){
            sumcol++;
            while(Stack[top+1]!=x){
                bel[Stack[top]]=sumcol;
                instack[Stack[top]]=false;
                mx[sumcol]=max(mx[sumcol],Stack[top]);
                top--;
            }
        }
    }
    
    void dfs(int x){
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(bel[x]==bel[v])continue;
            dfs(v);
            ans[bel[x]]=max(ans[bel[x]],ans[bel[v]]);
        }
        return;
    }
    
    int main(){
        freopen("graph.in","r",stdin);
        freopen("graph.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x,y;
            x=read();y=read();
            add(x,y);
        }
        if(n<=3000){
            for(int i=1;i<=n;i++)bfs(i);
            for(int i=1;i<=n;i++)printf("%d ",ans[i]);
            return 0;
            fclose(stdin);fclose(stdout);
        }
        for(int i=1;i<=n;i++)if(!dfn[i])tarjian(i);
        for(int x=1;x<=n;x++){
            for(int i=head[x];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(bel[v]!=bel[x]) cd[bel[x]]++,rd[bel[v]]++;
            }
        }
          for(int i=1;i<=n;i++)ans[bel[i]]=mx[bel[i]];
        for(int i=1;i<=n;i++)if(!rd[bel[i]])dfs(i);
        for(int i=1;i<=n;i++)printf("%d ",max(ans[bel[i]],mx[bel[i]]));
        fclose(stdin);fclose(stdout);
        return 0;
    }
    80

     缩点后,记录每个点的最大点权,那么某个点的能到达的最大点权就是

    所在环的最大点权和能到达的最大点权的Max。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define N 100008
    using namespace std;
    
    int n,m,sumedge,sume;
    queue<int>q;
    int head[N],hed[N];
    
    int ans[N],vis[N];
    
    int top,tim,sumcol;
    
    int low[N],dfn[N],Stack[N],instack[N],bel[N],mx[N];
    
    int cd[N],rd[N];
    
    inline int read(){
        char ch=getchar();int x=0,f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[N];
    
    struct E{
        int x,y,nxt;
        E(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }e[N];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void add_(int x,int y){
        e[++sume]=E(x,y,hed[x]);
        hed[x]=sume;
    }
    
    void tarjian(int x){
        low[x]=dfn[x]=++tim;
        Stack[++top]=x;instack[x]=true;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(instack[v])low[x]=min(low[x],dfn[v]);
            else if(!dfn[v]){
                tarjian(v);
                low[x]=min(low[x],low[v]);
            }
        }
        if(low[x]==dfn[x]){
            sumcol++;
            while(Stack[top+1]!=x){
                bel[Stack[top]]=sumcol;
                instack[Stack[top]]=false;
                mx[sumcol]=max(mx[sumcol],Stack[top]);
                top--;
            }
        }
    }
    
    void dfs(int x){
        if(vis[x])return ;
        vis[x]=true;ans[x]=mx[x];
        for(int i=hed[x];i;i=e[i].nxt){
            int v=e[i].y;
            dfs(v);
            ans[x]=max(ans[x],ans[v]);
        }
    }
    
    int main(){
    //    freopen("graph.in","r",stdin);
    //    freopen("graph.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x,y;
            x=read();y=read();
            add(x,y);
        }
        for(int i=1;i<=n;i++)if(!dfn[i])tarjian(i);
        for(int x=1;x<=n;x++){
            for(int i=head[x];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(bel[v]!=bel[x]) {
                    cd[bel[x]]++,rd[bel[v]]++;
                    add_(bel[x],bel[v]);
                }
            }
        }
          for(int i=1;i<=n;i++)ans[bel[i]]=mx[bel[i]];
        for(int i=1;i<=sumcol;i++)if(!vis[i])dfs(i);
        for(int i=1;i<=n;i++)printf("%d ",ans[bel[i]]);
        return 0;
    }
    AC缩点+dp

    Problem 2 Incr(incr.cpp/c/pas)

     

    【题目描述】

    数列 A1,A2,...,AN,修改最少的数字,使得数列严格单调递增。

     

    【输入格式】

    第 1 行,1 个整数 N

    第 2 行,N 个整数 A1,A2,...,AN

    【输出格式】

    1 个整数,表示最少修改的数字

     

    【样例输入】

    3

    1 3 2

    【样例输出】

    1

    【数据范围】

    对于 50% 的数据,N ≤ 10^3

    对于 100% 的数据,1 ≤ N ≤ 10^5,1 ≤ Ai ≤ 10^9

    题解:

     n-最长上升子序列长度

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 100008
    using namespace std;
    
    int n,ans;
    
    int a[N],dp[N];
    
    int main(){
        freopen("incr.in","r",stdin);
        freopen("incr.out","w",stdout);
        scanf("%d",&ans);
        for(int i=1;i<=ans;i++)scanf("%d",&a[i]);
        for(int i=1;i<=ans;i++)dp[i]=1;
        for(int i=1;i<=ans;i++)
         for(int j=1;j<i;j++)
           if(a[j]<a[i])dp[i]=max(dp[i],dp[j]+1);
        for(int i=1;i<=ans;i++)n=max(n,dp[i]);
        ans-=n;
        cout<<ans<<endl;
        fclose(stdin);fclose(stdout);
        return 0;
    } 
    50
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=0x3f3f3f3f;
    int n,a[1000009],dp[1000009];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        memset(dp,0x3f,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            int p=upper_bound(dp+1,dp+n+1,a[i])-dp;
            if(a[i]!=dp[p-1])//严格上升序列 
            dp[p]=a[i];
        }
        for(int i=1;i<=n+1;i++)
        {
            if(dp[i]==maxn)
            {
                printf("%d
    ",n-(i-1));
                return 0;
            }
        }
        return 0;
    }
    AC

    Problem 3 Permutation (permutation.cpp/c/pas)

     

    【题目描述】

    将 1 到 N 任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。

    问在所有排列中,有多少个排列恰好有K“<”。 

    例如排列(3, 4, 1, 5, 2)

    3 < 4 > 1 < 5 > 2

    共有2“<”

     

    【输入格式】

    N,K

     

    【输出格式】

    答案

     

    【样例输入】

    5 2

    【样例输出】

    66

    【数据范围】

    20%:N <= 10

    50%:答案在0..2^63-1内 

    100%:K < N <= 100

    题解:

    20暴力

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using namespace std;
    
    int n,k;
    
    int a[100];
    
    LL ans;
    
    int main(){
        freopen("permutation.in","r",stdin);
        freopen("permutation.out","w",stdout);
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)a[i]=i;
        do{
            int js=0;
            for(int i=2;i<=n;i++) if(a[i]>a[i-1])js++;
            if(js==k)ans++;
        }while(next_permutation(a+1,a+n+1));
        cout<<ans<<endl;
        fclose(stdin);fclose(stdout);
        return 0;
    }
    20

     f[i][j]表示前i个位置放j个小于号。

    i个数一共有i+1个位置,那么插入当前第i个数

    可能会产生小于号,也可能不会产生小于号

    不会产生小于号的情况是插在小于号上,一共有j+1个位置,

    会产生的有i-j个位置。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int n,k;
    
    int f[1020][1020];
    
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)f[i][0]=1;
        for(int i=1;i<=n;i++)
         for(int j=1;j<=k;j++)
          f[i][j]+=(f[i-1][j]*(j+1)+f[i-1][j-1]*(i-j))%2015;
        cout<<f[n][k];
        return 0;
    }
    AC
  • 相关阅读:
    安卓开发之ListAdapter(二)
    两listview联动
    不要天真了,这些简历HR一看就知道你是培训的,质量不佳的那种
    天真!这简历一看就是包装过的
    一线城市为何难逃离,职场饭局正在“失宠”?
    腾讯架构师分享的Java程序员需要突破的技术要点
    百度最穷程序员现身,工作4年晒出存款后,网友:你是真穷!
    震惊微软!招程序员的流程居然...
    python基础认识(一)
    input修改placeholder文字颜色
  • 原文地址:https://www.cnblogs.com/zzyh/p/7808615.html
Copyright © 2011-2022 走看看