zoukankan      html  css  js  c++  java
  • 【洛谷P6834】梦原

    题目

    题目链接:https://www.luogu.com.cn/problem/P6834
    不幸的是,这棵树尚未长成,只有一个根节点 \(1\)

    Cirno 只能知道这棵树将会有 \(n\) 个结点,上面分别有 \(a_1,a_2,\ldots,a_n\) 颗果实,却无法知道树的形状。

    但是树的生长总是具有某种规律。

    对于结点 \(i\),它会等概率地\([i-k,i-1] \cap N^+\) 中选择一个结点连接,并成为那个节点的子节点。

    其中,\(k\) 是一个 Cirno 已经测出的常数。

    为了摘下所有的果实,在树长成之后,Cirno 会多次使用魔法。其中每次会在树上选一个联通块,并从联通块内每个结点上摘取一个果子(必须保证该联通块内每个结点都有果子)。

    显然,Cirno 会采取最佳策略使得使用魔法的次数最少。

    现在,Cirno 已经知道了 \(n\)\(k\) 和每个结点将会长出的果子数 \(a_i\),请你帮她计算出她最少使用的魔法次数的数学期望。为了简单起见,你只需要输出答案除以 \(998244353\) 的余数。

    思路

    链的情况就是 铺设道路。贪心即可。
    放到树上之后,依然考虑贪心。从权值小到大枚举点,那么这个点的贡献应该为点权减去与该点相邻的点的期望深度。
    那么分成两部分来计算,第一部分就是编号在 \((x,x+m]\) 中的点,每一个点连向 \(x\) 的期望是不同的,所以我们维护一个树状数组,其中第 \(i\) 位就表示点 \(i\) 的权值除以 \(\min(m,i-1)\)。然后求区间和即可。
    对于编号在 \([x-m,x)\) 的点,每一个都有 \(\frac{1}{\min(m,x-1)}\) 的概率连向 \(x\),所以再维护一个树状数组求权值和,然后查询区间权值和除以 \(\min(m,x-1)\) 即可。
    时间复杂度 \(O(n\log n)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=1000010,MOD=998244353;
    int n,m;
    ll ans;
    
    struct node
    {
    	int id;
    	ll x;
    }a[N];
    
    bool cmp(node x,node y)
    {
    	return x.x<y.x;
    }
    
    ll fpow(ll x,int k)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=x*x%MOD)
    		if (k&1) ans=ans*x%MOD;
    	return ans;
    }
    
    struct BIT
    {
    	int c[N];
    	
    	void add(int x,ll v)
    	{
    		for (int i=x;i<=n;i+=i&-i)
    			c[i]=(c[i]+v)%MOD;
    	}
    	
    	ll query(int x)
    	{
    		ll ans=0;
    		for (int i=x;i;i-=i&-i)
    			ans+=c[i];
    		return ans%MOD;
    	}
    }bit,bit2;
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i].x);
    		a[i].id=i;
    	}
    	sort(a+1,a+1+n,cmp);
    	for (int i=1;i<=n;i++)
    	{
    		ll s=bit.query(min(a[i].id+m,n))-bit.query(a[i].id);
    		ll s2=(bit2.query(a[i].id-1)-bit2.query(max(a[i].id-m-1,0)))*fpow(min(m,a[i].id-1),MOD-2);
    		ans=(ans+(a[i].x-s-s2)%MOD+MOD)%MOD;
    		bit.add(a[i].id,a[i].x*fpow(min(m,a[i].id-1),MOD-2)%MOD);
    		bit2.add(a[i].id,a[i].x);
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    题解【bzoj3529 [SDOI2014]数表】
    题解【bzoj2301 [HAOI2011]Problem b】
    题解【bzoj2440 [中山市选2011]完全平方数】
    题解【bzoj3240 [NOI2013]矩阵游戏】
    题解【CF277E Binary Tree on Plane】
    题解【luogu2045 方格取数游戏加强版】
    题解【bzoj4650 [NOI2016]优秀的拆分】
    NOIp2018 游记
    Android提供的layout文件存放位置
    Android控件第2类——ImageView
  • 原文地址:https://www.cnblogs.com/stoorz/p/13697585.html
Copyright © 2011-2022 走看看