EOJ Monthly 2019.2 E. 中位数 (二分+dfs)

题目传送门

题意:

在一个n个点,m条边的有向无环图中,求出所有从1到n

的路径的中位数的最大值

一条路径的中位数指的是:一条路径有 n 个点,

将这 n 个点的权值从小到大排序后,排在位置 ⌊n2⌋+1 上的权值。

思路:

看到权值为1~1e9,可以想到用二分答案,然后我们在验证的时候

可以将小于mid的边权设为-1,大于为1这样遍历一遍序列加起来的值

刚好为0

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 1000005
const ll INF=2e9;
int n,m;
int a[N];
vector<int>v[N];
int dis[N];
int vis[N];

int dfs(int mid,int x)
{
   if(vis[x]) return dis[x];
   int tmp=a[x]>=mid?1:-1;
   vis[x]=1;
   for(int i=0;i<v[x].size();i++)
   {
       int t=v[x][i];
       dis[x]=max(dis[x],tmp+dfs(mid,t));
   }
   return dis[x];
}
bool check(int mid)
{
    for(int i=1;i<=n;i++) dis[i]=-INF;
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    dis[1]=a[1]>=mid?1:-1;
    return dfs(mid,n)>=0;
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            v[y].push_back(x);
        }
        ll l=0,r=INF;
        ll ans=-1;
        while(l<=r)
        {
            ll mid=l+r>>1;
            if(check(mid))
            {
                l=mid+1;
                ans=mid;
            }
            else r=mid-1;
        }
        printf("%lld\n",ans);
    }

    return 0;
}

原文地址:https://www.cnblogs.com/zhgyki/p/10463444.html

时间: 2024-08-30 15:44:04

EOJ Monthly 2019.2 E. 中位数 (二分+dfs)的相关文章

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

题意: 一张由 n 个点,m 条边构成的有向无环图.每个点有点权 Ai.QQ 小方想知道所有起点为 1 ,终点为 n 的路径中最大的中位数是多少. 一条路径的中位数指的是:一条路径有 n 个点,将这 n 个点的权值从小到大排序后,排在位置 ⌊n2⌋+1 上的权值. 思路(官方题解): 考虑二分答案,我们需要验证路径最大的中位数是否 ≥mid . 我们把所有的点权做 −1/1 变换,即 ≥mid 的点权变为 1 ,否则变为 −1 . 根据题面路径中位数的定义,我们可以发现,如果这条路径的中位数 ≥

EOJ Monthly 2019.2

题解 A 回收卫星 #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #defin

EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)

传送门 题意: 统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\). 定义\(f(n,k)\)为满足要求的\(k\)元组个数,现在要求出\(\sum_{i=1}^n f(i,k),1\leq n\leq 10^9,1\leq k\leq 1000\). 思路: 首先来化简一下式子,题目要求的就是: \[ \begin{aligned} &\sum_{i=1}^n\sum_{j=1

EOJ Monthly 2019.11 B字母游戏

题目见:https://acm.ecnu.edu.cn/contest/231/problem/B/ 卡在第二个点和第十二个点上无数次. 和226打电话,226建议双哈希,然后一发过了....(这是226大佬的力量啊) #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1005 const int mod[2]={19260817,19190504},mul[2]={29,11}; i

EOJ Monthly 2019.2 (based on February Selection) D.进制转换

题目链接: https://acm.ecnu.edu.cn/contest/140/problem/D/ 题目: 思路: 我们知道一个数在某一个进制k下末尾零的个数x就是这个数整除kx,这题要求刚好末尾有m个0,还需要除去高位为0的情况,因此这题答案就是r / kx-(l-1)/kx-(r/kx+1-(l-1)/kx+1). 代码实现如下: 1 #include <set> 2 #include <map> 3 #include <deque> 4 #include &

EOJ Monthly 2019.3A

A. 钝角三角形 单点时限: 3.0 sec 内存限制: 512 MB QQ 小方以前不会判断钝角三角形,现在他会了,所以他急切的想教会你. 如果三角形的三边长分别为 a, b, c (a≤b≤c),那么当满足 a2+b2<c2 且 a+b>c 的时候,这个三角形就是一个由三边长为 a, b, c 构成的钝角三角形. 单单讲给你听肯定是不够的,为了表现自己,QQ 小方现在要考考你. 现在 QQ 小方会给你一个包含 3n 个整数的集合,分别是 {2,3,4,?3n,3n+1} ,他想让你将这个集

[EOJ Monthly] 2019.9

https://acm.ecnu.edu.cn/contest/196/ 这次是ECNU的校内选拔应该会简单一点? 下午嘉定有彩虹,在村(学)子(校)里面转了一圈,学校真大,没什么人,火烧云真美,台风 要 来 了 打开比赛,看看D:要求概率 不会是签到 看看C:这么大的模拟,不是签到 看看A:要么找规律要么SG,然后很长时间都没有人过,可能是SG,算了不管了 后来队里面有人说D是知乎原题 拿到公式开始交 逆元用费马大定理求 敲敲敲... WA WOC??为什么WA,请教了大佬队友,费马大定理会爆

[BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】

题目链接:BZOJ - 1082 题目分析 二分 + DFS验证. 二分到一个 mid ,验证能否选 mid 个根木棍,显然要选最小的 mid 根. 使用 DFS 验证,因为贪心地想一下,要尽量先用提供的小的木木棍,尽量先做出需要的大的木棍,所以要先将提供的木棍和需要的木棍都排序. DFS 的时候是按照需要的木棍从大到小的顺序一层一层搜,每一层上是按照从小到大的顺序枚举提供的木棍.(当然枚举的时候已经不一定是从小到大了,有些木棍已经被截掉了一些.) 要使用两个有效的剪枝: 1)如果下一层的木棍和

【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

第一种做法(时间太感人): 这题我真的逗了,调了一下午,疯狂造数据,始终找不到错. 后来发现自己sb了,更新那里没有打id,直接套上u了.我.... 调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗 好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种. 树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要