2018分组赛Round1 (To be continue)

A AtCoder 3952

题解

计算前缀和,然后搞一下就出来了。

代码

#include<bits/stdc++.h>
using namespace std;
const int nmax = 2e5+10;
const int INF = 0x3f3f3f3f;
typedef long long ll;
typedef double db;
map<ll,ll> mpall;
map<ll,ll> mpfront;
int n;
ll a[nmax];
ll prefix[nmax];
int main(){
    scanf("%d",&n);
    for(int i = 1;i<=n;++i){
        scanf("%lld",&a[i]);
        if(i == 1) prefix[i] = a[i];
        else {
            prefix[i] = prefix[i-1] + a[i];
        }
        mpall[prefix[i]] ++;
    }
    ll sum = 0;
    ll cnt = 0;
    for(int i = 1;i<=n;++i){
        cnt += mpall[sum] - mpfront[sum];
        mpfront[prefix[i]] ++;
        sum += a[i];
    }
    printf("%lld\n",cnt);
    return 0;
}

B HDU - 5701

题解

和BZOJ那个中位数图很像,这道题时限开到6S,并且数据的组数并不是很多,所以直接 n 2 的暴力就可以过。不过在比赛的时候,我用的map存储的,所以导致时间复杂度上面多了一个 l o g .这就十分恐怖了,根据数据范围,多一个 l o g 会导致时间是原来为10倍,导致超时。

代码

#include<cstdio>
#include<cstring>
using namespace std;
const int nmax = 8050;
const int INF = 0x3f3f3f3f;
const int shift = 8005;
typedef long long ll;
//map<int,int> Lcnt,Rcnt;
//map<int,int> :: iterator it;
int n;
int a[nmax];
int tag[nmax];
int Lcnt[nmax<<1];
int Lprefix[nmax<<1],Rprefix[nmax<<1];
int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i = 1;i<=n;++i) scanf("%d",&a[i]);
        for(int i = 1;i<=n;++i){ //midpos
//            Lprefix[i] = Rprefix[i] = 0;
            int prefix = 0;
            memset(Lcnt,0,sizeof Lcnt);
            int temp = 1;
            for(int j = i-1;j>=1;--j){ //l
                tag[j] = a[j] > a[i] ? 1 : -1;
//                Lprefix[j] = Lprefix[j+1] + tag[j];
                prefix += tag[j];
                Lcnt[prefix + shift] ++;

            }
            prefix = 0;
            temp += Lcnt[0+shift];
            for(int j = i+1;j<=n;++j){//r
                tag[j] = a[j] > a[i] ? 1 : -1;
//                Rprefix[j] = Rprefix[j-1] + tag[j];
                prefix += tag[j];
                if(!prefix) temp++;
//                if(Rprefix[j] == 0) temp++;
                temp += Lcnt[-prefix + shift];
            }
//            printf("\n%d: ",i);
//            for(int i = 1;i<=n;++i) printf("%d ",Lcnt[i]); printf("\n");
            if(i!=n) printf("%d ",temp);
            else printf("%d\n",temp);
        }
    }
    return 0;
}

C AtCoder - 3953

题解

字符串哈希,还不会,等着补

D CodeForces - 148D

题解

概率DP, d p [ i ] [ j ] 表示有i个白色棋子,j个黑色棋子的胜利概率,然后推一推把3种情况都推出来就好了。

代码

#include<bits/stdc++.h>
using namespace std;
const int nmax = 1e6 ;
const int INF = 0x3f3f3f3f;
typedef long double ldb;
int w,b;
double dp[1005][1005];

int main() {
    while(scanf("%d%d",&w,&b)!=EOF){
        memset(dp,0,sizeof dp);
        for(int i = 1;i<=1000;++i) dp[i][0] = 1, dp[0][i] = 0;
        for(int i = 1;i<=w;++i){
            for(int j = 1;j<=b;++j){
                dp[i][j] = 1.0 * i / (i+j);
                if(i>=1 && j >=2) dp[i][j] += (1.0 * j / (i+j)) * (1.0 * (j-1) / (i + j - 1)) * (1.0 * (i) / (i + j - 2)) * dp[i-1][j-2];
                if(i>=0 && j >=3) dp[i][j] += (1.0 * j / (i+j)) * (1.0 * (j-1) / (i + j - 1)) * (1.0 * (j-2) / (i + j -2)) * dp[i][j-3];
            }
        }
        printf("%.10f\n",dp[w][b]);
    }
    return 0;
}

E CodeForces - 449B

题解

首先要知道如果从1到任意节点x,如果有铁路的话,最多有一条,并且我们只保留那一条最小的,这样的话,我们跑一边最短路,看看最短距离和铁路之间的关系,如果铁路在最短路径上,保留即可,不在则删掉。

代码

#include<bits/stdc++.h>
using namespace std;
const int nmax = 1e5 + 10 ;
const int INF = 1e12;
typedef long long ll;
int n,m,k;
typedef struct{
    int to, nxt;
    ll w;
}Edge;
Edge e[ (4 * nmax)<<1 ];
typedef pair<int,ll> pii;
vector<pii> ee[nmax];
ll dis[nmax];
int head[nmax<<1],cnt;
bool istrain[nmax],visit[nmax];
inline void add(int &  u, int & v, ll &  w){
    e[cnt].to = v, e[cnt].nxt = head[u], e[cnt].w = w;
    head[u] = cnt++;
}
int spfa(int s){
//    int CNT = 0;
//    bitset<nmax> visit; visit.reset();
    queue<int> q; q.push(s); visit[s] = 1;
    for(int i = 1;i<=n;++i) dis[i] = i == s? 0 : INF;
    for(int i = 1;i<=k;++i){
        int v;
        ll w;
        scanf("%d %I64d",&v,&w);
        if(dis[v] == INF) dis[v] = w, istrain[v] = true,q.push(v),visit[v] = 1;
        else if(dis[v] >= w){
            dis[v] = w;
//            CNT ++;
        }
    }
    while(!q.empty()){
        int u = q.front(); q.pop(); visit[u] = 0;
        for(int i = 0;i < ee[u].size() ;++i){
            int v = ee[u][i].first; ll w = ee[u][i].second;
            if(dis[u] + w <= dis[v]){
                dis[v] = dis[u] + w;
                if(istrain[v]) istrain[v] = false;
                if(!visit[v]){
                    q.push(v);
                    visit[v] = 1;
                }
            }
        }
    }
    int K = k;
    for(int i = 1;i<=n;++i) K -= istrain[i];
    return K;
}
int main() {
    scanf("%d%d%d",&n,&m,&k);
    memset(head,-1,sizeof head);
    for(int i = 1;i<=m;++i){
        int u,v;
        ll w;
        scanf("%d %d %I64d",&u,&v,&w);
        ee[u].push_back(make_pair(v,w));
        ee[v].push_back(make_pair(u,w));
//        add(u,v,w);
//        add(v,u,w);
    }
    printf("%d\n",spfa(1));
    return 0;
}

F AtCoder - 4143

题解

还没补

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/80876035