AtCoder Beginner Contest 194 D-E

Journey
给你 n n n个点的图,你一开始在第一个点,问你将图变成全联通的期望为多少
我们先思考下这个问题:给你 n n n个点,你每次可以随机涂一个,问你将所有点涂上颜色的期望为多少
期望 d p dp dp通常反着求解 设 d p [ i ] dp[i] dp[i] 代表涂好 i i i个点后将 n n n个点涂上颜色的期望,那么 d p [ n ] dp[n] dp[n] = 0 0 0 d p [ i ] dp[i] dp[i] = ( i / n ) d p [ i ] (i/n)dp[i] (i/n)dp[i] + ( n − i ) / n ∗ d p [ i + 1 ] (n-i)/n * dp[i+1] (ni)/ndp[i+1] + 1 1 1 d p [ i ] dp[i] dp[i] = d p [ i + 1 ] dp[i+1] dp[i+1] + ( n ) / ( n − i ) (n)/(n-i) (n)/(ni)
那么我们思考下现在的问题 不就是已经给你涂好一个点了吗?
那么我们只要按照所求的式子最后 -1 即可 一个点已经涂好了

#include<iostream>
#include<cstdio>
using namespace std;

#define ll long long
const int MAX_N = 100025;
double dp[MAX_N];

int main()
{
    int n;
    scanf("%d",&n);
    dp[n] = 0;
    for(int i = n-1;i>=0;--i)
    {
        dp[i] = dp[i+1] + ((1.0*(n)/(n-i)));
    }
    printf("%.6f\n",dp[0]-1);
}


Mex Min
定义 Mex 为在一段区间内出现的最小非负数,那么我们容易想到用树状数组维护一个前缀和 二分用 g e t ( i ) = = i get(i)==i get(i)==i判断即可 注意因为要最小非负数 0 0 0是ok的 而树状数组在处理 0 0 0时候会有问题 所以我们需要将下标进行处理

#include<cstdio>
#include<iostream>
using namespace std;
const int MAX_N = 2000005;

#define dbg(x) cout << #x << " = " << (x) << endl;
#define dbg2(x,y) cout << #x << " = " << (x) << " " << #y << " = " << (y) << endl;
#define dbg3(x,y,z) cout << #x << " = " << (x) << " " << #y << " = " << (y) << " " << #z << " = " << (z) << endl;

int arr[MAX_N],cnt[MAX_N],S[MAX_N<<1];

void add(int x,int v)
{
    for(;x<MAX_N;x+=x&(-x))
    {
        S[x]+=v;
    }
}

int get(int x)
{
    int sum = 0;
    for(;x;x-=x&(-x))
    {
        sum+=S[x];
    }
    return sum;
}

int main()
{

    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n;++i)
    {
        scanf("%d",&arr[i]);
        arr[i]++;
    }
    int minn = 0x3f3f3f3f;
    for(int i = 1;i<=n;++i)
    {
        if(cnt[arr[i]]==0) add(arr[i],1);
        cnt[arr[i]]++;
        if(i>=m)
        {
            if(i>m&&cnt[arr[i-m]]==1) add(arr[i-m],-1);
            if(i>m) cnt[arr[i-m]]--;
            int l = 1,r = n+1;
            while(l<=r)
            {
                if(get(1)!=1)
                {
                    r = 1;
                    break;
                }
                int mid = l + r >> 1;
                if(get(mid)==mid) l = mid + 1;
                else r = mid - 1;
            }
            if(get(r)==r) r++;
            minn = min(minn,r);
        }
    }
    printf("%d\n",minn-1);
    return 0;
}

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页