• 暑期测试训练3


    1.Codeforces 20C

    spfa算法的简单题,在这个过程中多了一个记录连接最短路径上的前一个节点的位置的数组,然后将这个数组逆向输出

    在这道题目中,我路径数组范围居然忘记*2了,结果一直报错,找了好久,%>_<%

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    using namespace std;
    #define N 100010
    #define LL long long
    
    LL dp[N];
    int first[N],visit[N],k,n,f[N],r[N];
    
    struct Path{
        int y,d,next;
    }path[2*N];
    void add(int a,int b,int c)
    {
        path[k].y=b,path[k].d=c,path[k].next=first[a];
        first[a]=k;
        k++;
    }
    bool spfa(int src)
    {
        bool judge=false;
        memset(dp,-1,sizeof(dp));
        memset(f,0,sizeof(f));
        memset(visit,0,sizeof(visit));
        queue<int> q;
        dp[src]=0,visit[src]=1;
        q.push(src);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            visit[u]=0;
            for(int i=first[u];i!=-1;i=path[i].next){
                if(dp[path[i].y]==-1||dp[path[i].y]>dp[u]+path[i].d){
                    dp[path[i].y]=dp[u]+path[i].d;
                    f[path[i].y]=u;
                    if(!visit[path[i].y])
                    {
                        visit[path[i].y]=1,q.push(path[i].y);
                        if(path[i].y==n)
                            judge=true;
                    }
                }
            }
        }
        return judge;
    }
    int main()
    {
        int m,a,b,c;
        while(scanf("%d%d",&n,&m)!=EOF){
            k=0;
            memset(first,-1,sizeof(first));
            for(int i=0;i<m;i++){
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
            }
            if(!spfa(1)){
                printf("-1
    ");
                continue;
            }
            int cnt=0;
            for(int i=n;i!=0;i=f[i])
                r[cnt++]=i;
    
            for(int i=cnt-1;i>=1;i--)
                printf("%d ",r[i]);
            printf("%d
    ",r[0]);
        }
        return 0;
    }
    
    
     
    View Code

    2.CodeForces 295B
    这道题需计算所有节点对的最短路径和,所以用floyd算法,这里是不断删除节点,对于一个图来说,不断添加节点总是比不断删除节点要简单的多的,所以这道题逆向

    考虑,从最后往前面不断加入节点

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include <algorithm>
    using namespace std;
    #define N 502
    #define LL long long
    
    int n,dp[N][N],v[N];
    LL ans[N];
    void floyd(int k)
    {
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
            }
        }
    }
    LL query(int t)
    {
        LL sum=0;
        for(int i=n;i>=t;i--)
            for(int j=n;j>=t;j--)
                sum+=dp[v[i]][v[j]];
        return sum;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&dp[i][j]);
            for(int i=1;i<=n;i++) scanf("%d",&v[i]);
            for(int i=n;i>=1;i--){
                floyd(v[i]);
                ans[i]=query(i);
            }
            for(int i=1;i<=n-1;i++)
                printf("%I64d ",ans[i]);
            printf("%I64d
    ",ans[n]);
        }
        return 0;
    }
    View Code

    3.SPOJ MULTQ3
    这道题目特别容易超时。。。我就不吐槽我自己一会提交成功一会TLE了,感觉要看运气~~

    这道题目主要考虑在pushdown上面的修改,因为是否为3的整数倍,中间有余1和余2两种情况要进行考虑

    另外我们增添两个数组来保存余1和余2的个数,当然你也可以考虑用2维数组,这里情况比较少,多建几个数组也不是很麻烦

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define N 100005
    int sum1[4*N],sum2[4*N],sum3[4*N],a[N],add[4*N];
    
    void update(int cur)
    {
        sum1[cur]=sum1[cur<<1]+sum1[cur<<1|1];
        sum2[cur]=sum2[cur<<1]+sum2[cur<<1|1];
        sum3[cur]=sum3[cur<<1]+sum3[cur<<1|1];
    }
    void build(int cur,int x,int y)
    {
        add[cur]=0;
        int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
        if(x==y){
            sum1[cur]=1;
            sum2[cur]=0;
            sum3[cur]=0;
            return;
        }
        build(ls,x,mid);
        build(rs,mid+1,y);
        update(cur);
    }
    
    void pushdown(int cur,int x,int y)
    {
        int ls=cur<<1,rs=cur<<1|1;
        if(add[cur]%3!=0)
        {
            add[ls]+=add[cur],add[rs]+=add[cur];
            if(add[cur]%3==1){
                int temp=sum1[ls];
                sum1[ls]=sum3[ls];
                sum3[ls]=sum2[ls];
                sum2[ls]=temp;
                temp=sum1[rs];
                sum1[rs]=sum3[rs];
                sum3[rs]=sum2[rs];
                sum2[rs]=temp;
            }
            else if(add[cur]%3==2){
                int temp=sum2[ls];
                sum2[ls]=sum3[ls];
                sum3[ls]=sum1[ls];
                sum1[ls]=temp;
                temp=sum2[rs];
                sum2[rs]=sum3[rs];
                sum3[rs]=sum1[rs];
                sum1[rs]=temp;
            }
            add[cur]=0;
        }
    }
    
    void change(int cur,int x,int y,int s,int t,int v)
    {
        int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
        if(x>=s&&y<=t){
            int temp;
            temp=sum1[cur];
            sum1[cur]=sum3[cur];
            sum3[cur]=sum2[cur];
            sum2[cur]=temp;
            add[cur]+=v;
            return;
        }
        pushdown(cur,x,y);
        if(mid>=s) change(ls,x,mid,s,t,v);
        if(mid+1<=t) change(rs,mid+1,y,s,t,v);
        update(cur);
    }
    void query(int cur,int x,int y,int s,int t,int &ans)
    {
        int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
        if(x>=s&&y<=t){
            ans+=sum1[cur];
            return;
        }
        pushdown(cur,x,y);
        if(mid>=s) query(ls,x,mid,s,t,ans);
        if(mid+1<=t) query(rs,mid+1,y,s,t,ans);
    }
    int main()
    {
        int n,q,log,a,b;
        while(scanf("%d%d",&n,&q)!=EOF){
            build(1,0,n-1);
            for(int i=0;i<q;i++){
                scanf("%d",&log);
                if(log==0){
                    scanf("%d%d",&a,&b);
                    change(1,0,n-1,a,b,1);
                }
                else{
                    scanf("%d%d",&a,&b);
                    int ans=0;
                    query(1,0,n-1,a,b,ans);
                    printf("%d
    ",ans);
                }
            }
        }
        return 0;
    }
    View Code

    4.CodeForces 4C
    最基础的Map题,熟悉一下map的简单用法

    #include <iostream>
    #include <cstdio>
    #include <map>
    using namespace std;
    #define N 100010
    int n;
    int main()
    {
        map<string,int> a;
        string s;
        while(scanf("%d",&n)!=EOF){
            cin>>s;
            a[s]++;
            if(a[s]>1){
                cout<<s<<a[s]-1<<endl;
            }
            else cout<<"OK"<<endl;
        }
        return 0;
    }
    View Code

    5.SPOJ ROCK
    Dp题,据说很简单~~~反正我做不出。。。还是太水了

    这里dp[i]表示在前i段可以卖出的最大长度

    在第j段后面砍一刀,如果砍出来的那一段甜的成分大于酸的成份,再进行

    dp[i]=max(dp[i],dp[j]+i-j)的更新操作

    每次一个i结束循环,都进行一下dp[i]=dp[i-1]的更新操作,保证时刻都能更新到最大值

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 203
    char ch[N];
    int dp[N],sum[N][2];
    int main()
    {
        int T,n;
        scanf("%d",&T);
        while(T--){
            memset(dp,0,sizeof(dp));
            scanf("%d",&n);
            //sum[0][0]=sum[0][1]=0;
            for(int i=1;i<=n;i++)
            {
                cin>>ch[i];
                sum[i][1]=sum[i-1][1];
                sum[i][0]=sum[i-1][0];
                sum[i][ch[i]-'0']++;
            }
            for(int i=1;i<=n;i++){
                dp[i]=dp[i-1];
                for(int j=0;j<i;j++)
                    if(sum[i][1]-sum[j][1]>sum[i][0]-sum[j][0])
                        dp[i]=max(dp[j]+i-j,dp[i]);
            }
            cout<<dp[n]<<endl;
        }
        return 0;
    }
    View Code

    6.SPOJ NITK06
    居然拿第六题作为签到题,太可恶了。

    简单讲一下,只要奇数位上的和等于偶数位上的和这个就成立了

    #include <iostream>
    
    using namespace std;
    #define N 10005
    int a[N];
    int main()
    {
        int T,n,odd,even;
        cin>>T;
        while(T--){
            cin>>n;
            odd=0,even=0;
            for(int i=1;i<=n;i++)
            {
                cin>>a[i];
                if(i%2==0) even+=a[i];
                else odd+=a[i];
            }
            if(odd==even) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    随笔:我为什么要写博客?
    用纯C语言写的一个植物大战僵尸的外挂
    方法:如何获取操作系统所有分区(逻辑驱动器)
    Srping syntactically incorrect.错误记录
    重建项目报错
    easyui datagrid 跨页选择
    CentOS 6编译安装ipvsadm和keepalived
    CentOS 6下ActiveMQ 5.5安装及使用MySQL
    extjs 4中TreePanel和GridPanel使用
    Linux安装性能问题
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3888312.html
Copyright © 2020-2023  润新知