codeforces #301 div2

A:简单题

每次判断向上转快,还是向下转快即可

#include <cstdio>

#include <cstring>

#include <iostream>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

#define N 10005

#define ll long long

char s1[N] , s2[N];



int main()

{

   // freopen("a.in" , "r" , stdin);

    int n;

    while(~scanf("%d" , &n))

    {

        scanf("%s%s" , s1 , s2);

        int ans=0;

        for(int i=0 ; i<n ; i++){

            int a=s1[i]-'0';

            int b=s2[i]-'0';

            if(a>b){

                int t=a;

                a=b;

                b=t;

            }

            ans += min(b-a , 10+a-b);

        }

        printf("%d\n" , ans);

    }

    return 0;

}
View Code

 

B:贪心

先判断所给的数中能否已经保证中位数大于y,不能的话,添加尽可能少的y使其满足中位数为y,剩下的值全定为1,判断总和是否超过x

#include <cstdio>

#include <cstring>

#include <iostream>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

#define N 10005

#define ll long long

int n,k,p,x,y;

int a[N];

int main()

{

   // freopen("a.in" , "r" , stdin);

    int n;

    while(~scanf("%d%d%d%d%d" , &n,&k,&p,&x,&y))

    {

        int pos = (n+1)/2;

        int cnt1 = 0 , cnt2=0;

        int sum=0;

        for(int i=1 ; i<=k ; i++){

            scanf("%d" , &a[i]);

            if(a[i]>=y) cnt1++;

            else cnt2++;

            sum+=a[i];

        }



        if(cnt1>n-pos){

            for(int i=k+1 ; i<=n ; i++) a[i]=1,sum++;

            if(sum<=x){

                for(int i=k+1 ; i<=n ; i++){

                    if(i<n) printf("%d " , a[i]);

                    else printf("%d\n" , a[i]);

                }

            }

            else{

                puts("-1");

            }

        }else{

            bool flag=true;

            if(pos-cnt1>n-k) flag=false;

            else{

                int i;

                for(i=k+1 ; i<=k+pos-cnt1 ; i++){

                    a[i] = y;

                    sum+=a[i];

                }

                for(;i<=n;i++){

                    a[i]=1;

                    sum+=a[i];

                }

                if(sum>x) flag=false;

            }

            if(flag){

                for(int i=k+1 ; i<=n ; i++){

                    if(i<n) printf("%d " , a[i]);

                    else printf("%d\n" , a[i]);

                }

            }

            else puts("-1");

        }

    }

    return 0;

}
View Code

 

C:bfs

从起点bfs,判断能否有两条路径到达终点即可

#include <cstdio>

#include <cstring>

#include <iostream>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

#define N 1005

#define ll long long

int n , m;

int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};



struct Point{

    int x,y;

    Point(int x=0 , int y=0):x(x),y(y){}

}p[N][N];

int mat[N][N];

char s[N][N];

Point st , en;

queue<Point> q;



bool ok(int x , int y)

{

    return x>0 && x<=n && y>0 && y<=m;

}



bool bfs()

{

    while(!q.empty()) q.pop();

    q.push(st);

    while(!q.empty())

    {

        Point u = q.front();

        q.pop();

        for(int i=0 ; i<4 ; i++){

            int xx = u.x+dir[i][0];

            int yy = u.y+dir[i][1];

            if(!ok(xx,yy)) continue;

            if(mat[xx][yy]==0){

                mat[xx][yy]=-1;

              //  cout<<"in: "<<u.x<<" "<<u.y<<" to: "<<xx<<" "<<yy<<endl;

                q.push(Point(xx,yy));

            }

            else if(mat[xx][yy]==-1 && xx==en.x && yy==en.y){

              //  cout<<"in: "<<u.x<<" "<<u.y<<endl;

                return true;

            }

        }

    }

    return false;

}



int main()

{

  //  freopen("a.in" , "r" , stdin);



    while(~scanf("%d%d" , &n,&m))

    {

        for(int i=1 ; i<=n ; i++)

            scanf("%s" , s[i]+1);

        for(int i=1 ; i<=n ; i++){

            for(int j=1 ; j<=m ; j++){

                if(s[i][j] == '.'){

                    mat[i][j]=0;

                }

                else mat[i][j]=-1;

            }

        }



        scanf("%d%d" , &st.x , &st.y);

        scanf("%d%d" , &en.x , &en.y);



        printf("%s\n" , bfs()?"YES":"NO");

    }

    return 0;

}
View Code

 

D:概率DP

dp[i][j][k] 表示剩余i个rock,j个siccsors,k个paper时的概率

初始dp[r][q][s]=1

状态转移

dp[i][j][k]+=dp[i+1][j][k]*(1.0*(i+1)*k/((i+1)*j+(i+1)*k+k*j)); dp[i][j][k]+=dp[i][j+1][k]*(1.0*(j+1)*i/(i*(j+1)+i*k+(j+1)*k)); dp[i][j][k]+=dp[i][j][k+1]*(1.0*(k+1)*j/(i*j+i*(k+1)+j*(k+1)));

#include <cstdio>

#include <cstring>

#include <iostream>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

#define N 210

#define ll long long



double dp[N][N][N];

int r,s,q;



void solve()

{

    memset(dp,0,sizeof(dp));

    dp[r][s][q]=1.0;

    for(int i=r ; i>=0 ; i--){

        for(int j=s ; j>=0 ; j--){

            for(int k=q ; k>=0 ; k--){

                if(i==r && j==s && k==q) continue;

                dp[i][j][k] = 0;

                if(k) dp[i][j][k]+=dp[i+1][j][k]*(1.0*(i+1)*k/((i+1)*j+(i+1)*k+k*j));

                if(i) dp[i][j][k]+=dp[i][j+1][k]*(1.0*(j+1)*i/(i*(j+1)+i*k+(j+1)*k));

                if(j) dp[i][j][k]+=dp[i][j][k+1]*(1.0*(k+1)*j/(i*j+i*(k+1)+j*(k+1)));

              //  cout<<i<<" "<<j<<" "<<k<<" "<<dp[i][j][k]<<endl;

            }

        }

    }

}



int main()

{

   // freopen("a.in" , "r" , stdin);



    while(~scanf("%d%d%d" , &r,&s,&q))

    {

        solve();

        double ans1=0 , ans2=0 , ans3=0;

        for(int i=1 ; i<=r ; i++) ans1+=dp[i][0][0];

        for(int i=1 ; i<=s ; i++) ans2+=dp[0][i][0];

        for(int i=1 ; i<=q ; i++) ans3+=dp[0][0][i];

        printf("%.11f %.11f %.11f\n" , ans1 , ans2 , ans3);

    }

    return 0;

}
View Code

 

E:线段树

将点离散化后保存到线段树上,那么最多有200000个点

逐个添加,判断离散化的点之间可以形成多少对

在计算每个离散化的点和其他非离散化的区间内的点形成了多少对

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

#define N 200010

#define ls o<<1

#define rs o<<1|1

#define define_m int m=(l+r)>>1

#define ll long long

int a[N*2] , k , p[N] , q[N] , val[N*2];

ll sum[N<<2];

ll ans=0;



int getIndex(int key)

{

    return lower_bound(a , a+k , key)-a;

}



void push_up(int o)

{

    sum[o] = sum[ls]+sum[rs];

}



void update(int o , int l , int r , int pos)

{

    if(l==r && l==pos){

        sum[o]++;

        return ;

    }

    define_m;

    if(m>=pos) update(ls , l , m , pos);

    else update(rs , m+1 , r , pos);

    push_up(o);

}



int query(int o , int l , int r , int s , int t)

{

    if(l>r) return 0 ;

    if(l>=s && r<=t){

        return sum[o];

    }

    int ans=0;

    define_m;

    if(m>=s) ans+=query(ls , l , m , s , t);

    if(m<t) ans+=query(rs , m+1 , r , s , t);

    return ans;

}



int main()

{

   // freopen("a.in" , "r" , stdin);

    int n;

    while(~scanf("%d" , &n))

    {

        k=0;

        for(int i=0 ; i<n ; i++){

            scanf("%d%d" , &p[i] , &q[i]);

            a[k++]=p[i] , a[k++]=q[i];

        }

        sort(a , a+k);

        k = unique(a , a+k)-a;

        for(int i=0 ; i<n ; i++){

            int index = getIndex(p[i]);

            val[index] = p[i];

            p[i] = index;

            index = getIndex(q[i]);

            val[index] = q[i];

            q[i]=index;

        }

        for(int i=0 ; i<n ; i++) swap(val[p[i]] , val[q[i]]);

        ans = 0;

        memset(sum , 0 , sizeof(sum));

        for(int i=0 ; i<k ; i++){

            int index = getIndex(val[i]);

            ans += (ll)query(1 , 0 , k-1 , index+1 , k-1);

            update(1 , 0 , k-1 , index);

        }

        //判断当前第i个点和所有非离散化区间能形成的匹配

        for(int i=0 ; i<k ; i++){

            ans += (ll)abs(val[i]-val[getIndex(val[i])]) - (ll)abs(i-getIndex(val[i]));

        }

        cout<<ans<<endl;

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(codeforces)