Codeforce 445(A,B,C,D,E)

A.链接:点击打开链接

题意:在一个N*M的棋盘上,'.'为可放棋的点,'-'为不放棋的点,有'B'和'W'两种棋,要求这两种棋不能相邻,输出满足条件的棋盘

代码:

<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main(){
    int n,m,i,j,k;
    char s[105][105];
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(s,0,sizeof(s));                  //就是一个国际象棋的棋盘...
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        scanf(" %c",&s[i][j]);
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                if(s[i][j]=='.'){
                    if(i%2){
                        if(j%2)
                        printf("B");
                        else
                        printf("W");
                    }
                    else{
                        if(j%2)
                        printf("W");
                        else
                        printf("B");
                    }
                }
                else
                printf("%c",s[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
 }</span>

 

B.链接:点击打开链接

题意:有n种药品,m种反应,反应可以翻倍,例如1,2反应,2,3反应,则当1在试管中时,将2放入试管种威力乘2,再将3放入试管中,威力则再乘2,初始威力为1,输出最后的威力

代码:

<span style="font-size:18px;">#include <queue>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int par[105],r[105];
int find(int x){
    if(x==par[x])
    return x;
    return par[x]=find(par[x]);
}
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y)
    return;
    if(r[x]<r[y])
    par[x]=y;
    else{
        par[y]=x;
        if(r[x]==r[y])
        r[x]++;
    }
}
bool same(int x,int y){
    return find(x)==find(y);
}                                               //并查集模板
int main(){
    int i,j,n,m,a,b,ans,sum;
    while(scanf("%d%d",&n,&m)!=EOF){
        ans=0;
        for(i=0;i<=n;i++){
            par[i]=i;
            r[i]=0;
        }
        while(m--){
            scanf("%d%d",&a,&b);
            unite(a,b);
        }
        sum=0;
        for(i=1;i<=n;i++){
        if(par[i]==i){
        sum++;
        }                                       //注意求的其实是联通数的个数
        }
        printf("%I64d\n",(long long)pow(2,n-sum));
    }
    return 0;
 }</span>


C.链接:点击打开链接

题意:有一个图,每个顶点有一个权值,每一条边有一个权值,求边的权值除以边两个顶点的权值的和的最大值

代码:

<span style="font-size:18px;">#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int num[505];
int main(){
    int n,m,i,j,a,b,c,p,q;
    double s,ans;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(i=1;i<=n;i++)
        scanf("%d",&num[i]);
        ans=0;
        while(m--){
            scanf("%d%d%d",&a,&b,&c);
            ans=max(ans,(num[a]+num[b])*1.0/c);
        }
        printf("%.15lf\n",ans);
    }
    return 0;
 }</span>


D.链接:点击打开链接

题意:由题目给出的一段程序,随机给出数组a和数组b,根据下图公式输出数组c

代码:

<span style="font-size:18px;">#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
long long n,d,x;
long long a[500005],b[500005],c[500005];
long long getNextX(){
    x=(x*37+10007)%1000000007;
    return x;
}
long long initAB(){
    long long i;
    for(i=0;i<n;i=i+1)
    a[i]=i+1;
    for(i=0;i<n;i=i+1)
    swap(a[i],a[getNextX()%(i+1)]);
    for(i=0;i<n;i=i+1){
        if(i<d)
        b[i]=1;
        else
        b[i]=0;
    }
    for(i=0;i<n;i=i+1)
    swap(b[i],b[getNextX()%(i + 1)]);
}
int main(){
    long long i,j,ans;
    while(scanf("%I64d%I64d%I64d",&n,&d,&x)!=EOF){
    initAB();
    vector<long long> v;
    for(i=0;i<n;i++)
    if(b[i])
    v.push_back(i);                             //因为数组b只能是0或1,因此b中1的个数决定了算出c的复杂度
    if(v.size()<(long long)sqrt(n)){            //当b中1的个数较少时,可以直接输出c    
        for(i=0;i<n;i++){
            ans=0;
            for(j=0;j<v.size()&&v[j]<=i;j++)
            ans=max(ans,a[i-v[j]]);
            printf("%I64d\n",ans);
        }
    }
    else{
        for(i=0;i<=n;i++)
        c[i]=n+1;
        for(i=0;i<n;i++)
        c[a[i]]=i;
        for(i=0;i<n;i++){
            for(j=n;j>0;j--){                   //记录每个值的位置,判断最近的数组b为1的位置
                if(c[j]<=i&&b[i-c[j]]){
                    printf("%I64d\n",j);
                    break;
                }
            }
            if(j==0)
            puts("0");
        }
    }
    }
    return 0;
}</span>


E.链接:点击打开链接

题意:给出n个数,初始为1~n,有m个操作,一种是将区间[l,r]内的值改为x,同时改点会累加一个|x-y|的值,第二种询问[l,r]区间内产生的累加值的和

代码:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
const long long SIZE=100005;                    //用两个标记,一个是懒惰标记,另一个是判断该节点表示的
long long cnt[SIZE<<2],add[SIZE<<2],sum[SIZE<<2];                    
void pushup(int rt){                            //区间是否是同一个值
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    if(cnt[rt<<1]&&cnt[rt<<1]==cnt[rt<<1|1])
    cnt[rt]=cnt[rt<<1];
    else
    cnt[rt]=0;
}
void pushdown(long long rt,long long m){
    if(add[rt]){
        add[rt<<1]+=add[rt];
        add[rt<<1|1]+=add[rt];
        sum[rt<<1]+=add[rt]*(m-(m>>1));
        sum[rt<<1|1]+=add[rt]*(m>>1);
        cnt[rt<<1]=cnt[rt<<1|1]=cnt[rt];
        add[rt]=0;
    }
}
void build(long long l,long long r,long long rt){
    long long m;
    add[rt]=sum[rt]=0;
    if(l==r){
        cnt[rt]=l;
        return ;
    }
    m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void update(long long L,long long R,long long c,long long l,long long r,long long rt){
    long long m;
    if(L<=l&&r<=R&&cnt[rt]){                    //同一个值才更新
        add[rt]+=abs(cnt[rt]-c);
        sum[rt]+=abs(cnt[rt]-c)*(r-l+1);        //不是同一个值就无法直接懒惰标记更新
        cnt[rt]=c;
        return;
    }
    pushdown(rt,r-l+1);
    m=(l+r)>>1;
    if(L<=m)
    update(L,R,c,l,m,rt<<1);
    if(R>m)
    update(L,R,c,m+1,r,rt<<1|1);
    pushup(rt);
}
long long query(long long L,long long R,long long l,long long r,long long rt){
    long long m,ans;
    if(L<=l&&r<=R)
    return sum[rt];
    pushdown(rt,r-l+1);
    ans=0;
    m=(l+r)>>1;
    if(L<=m)
    ans+=query(L,R,l,m,rt<<1);
    if(R>m)
    ans+=query(L,R,m+1,r,rt<<1|1);
    return ans;
}                                               //线段树区间询问
int main(){
    long long n,m,i,j,a,b,c,ch,sign;
    while(scanf("%I64d%I64d",&n,&m)!=EOF){
        build(1,n,1);
        while(m--){
            scanf("%I64d",&ch);
            if(ch==2){
                scanf("%I64d%I64d",&a,&b);
                printf("%I64d\n",query(a,b,1,n,1));
            }
            else{
                scanf("%I64d%I64d%I64d",&a,&b,&c);
                update(a,b,c,1,n,1);
            }
        }
    }
    return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值