• EOJ Monthly 2019.2 E 中位数 (二分+中位数+dag上dp)


    题意:

    一张由 n 个点,m 条边构成的有向无环图。每个点有点权 Ai。QQ 小方想知道所有起点为 1 ,终点为 n 的路径中最大的中位数是多少。

    一条路径的中位数指的是:一条路径有 n 个点,将这 n 个点的权值从小到大排序后,排在位置 n2+1 上的权值。

    思路(官方题解):

    考虑二分答案,我们需要验证路径最大的中位数是否 mid 。

    我们把所有的点权做 1/1 变换,即 mid 的点权变为 1 ,否则变为 1 。

    根据题面路径中位数的定义,我们可以发现,如果这条路径的中位数 mid ,那么做了 1/1 变换以后,这条路径上的点权和 0 。

    而我们现在需要知道的问题是路径最大的中位数是否 mid ,也就是说,最大的路径点权是否 0 。

    跑一遍最长路就好了。而对于 DAG ,最长路只要 dp 一下,复杂度是保证 O(m) 。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<cmath>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 1e6+100;
    const int maxm = 1e6+100;
    const int inf = 0x3f3f3f3f;
    
    int a[maxn];
    int b[maxn];
    vector<int>v[maxn];
    int dp[maxn];
    int n,m;
    int c(int x, int mid){
        return a[x]>=mid?1:-1;
    }
    void dpp(int x, int va,int mid){
        //printf("%d %d %d
    ",x,va,mid);
        if(va<=dp[x])return;
        dp[x] = max(dp[x],va);
        //if(x==n)return;
        for(int i = 0; i < (int)v[x].size(); i++){
            dpp(v[x][i], va+c(v[x][i],mid),mid);
        }
        return;
    }
    bool ck(int x){
        //x = b[x];
        for(int i = 1; i <= n; i++)dp[i]=-0x3f3f3f3f;
        dpp(1,c(1,x),x);
        
        if(dp[n]>=0)return true;
        return false;
    }
    int main(){
        scanf("%d %d",&n,&m);
        for(int i =1 ; i <= n; i++){
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= m; i++){
            int x, y;
            scanf("%d %d", &x, &y);
            v[x].pb(y);
        }
        //printf("%d",ck(5));
        int l = 0, r = 1e9;
        int ans=-1;
        while(l<=r){
            int mid = (r+l)>>1;
            //printf("%d %d %d
    ",l,r,mid);
            if(ck(mid)){
                l = mid+1;
                ans=mid;
            }
            else r = mid-1;
        }
        printf("%d", ans);
        return 0;
    }
  • 相关阅读:
    html基础知识点
    uni-app之tabBar的自己配置
    uni-app之导航配置pages.json
    js获取链接?后边的参数名称或者值
    验证码输入自动聚焦下一个input或者删除自动聚焦上一个input
    VUE中/deep/深度作用域
    vue环境下新建项目
    vue中展示数据
    VUE环境项目搭建以及简单的运行例子
    ios设置音乐audio自动播放
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10427173.html
Copyright © 2020-2023  润新知