• #树状数组,概率,离散,双指针#洛谷 6834 [Cnoi2020]梦原


    题目


    分析

    如果是序列((k=1))也就是积木大赛
    那也就是(sum_{i=1}^nmax{a_i-a_{i-1},0})
    那关键就是要处理与父节点之间的关系,如果父节点的值小于该节点的值才能产生贡献,
    那么用树状数组维护小于该节点的值的父节点的个数及权值和,并用双指针删除不合法的父节点即可


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=1000011,mod=998244353;
    int c[N],C[N],a[N],b[N],inv[N],n,TOT,m,ans;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline void add(int x,int y,int z){
    	for (;x<=TOT;x+=-x&x) c[x]=mo(c[x],y),C[x]+=z;
    }
    inline signed query(int x,int &t){
    	rr int ans=0; t=0;
    	for (;x;x-=-x&x)
    	    ans=mo(ans,c[x]),t+=C[x];
    	return ans;
    }
    signed main(){
    	n=iut(),m=iut(),inv[0]=inv[1]=1;
    	for (rr int i=2;i<=n;++i)
    	     inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	for (rr int i=1;i<=n;++i) b[i]=a[i]=iut();
    	sort(b+1,b+1+n),TOT=unique(b+1,b+1+n)-b-1;
    	for (rr int i=1;i<=n;++i)
    	    a[i]=lower_bound(b+1,b+1+TOT,a[i])-b;
    	add(a[1],ans=b[a[1]],1);
    	for (rr int i=2,j=1;i<=n;++i){
    		for (;j<i-m;add(a[j],mod-b[a[j]],-1),++j);
    		rr int CNT,NOW=query(a[i],CNT);
    		ans=mo(ans,1ll*mo(1ll*b[a[i]]*CNT%mod,mod-NOW)*inv[i-j]%mod);
    		add(a[i],b[a[i]],1);
    	}
    	return !printf("%d",ans);
    } 
    
  • 相关阅读:
    proguard-rules.pro、混淆、导jar包
    百度地图相关开发
    开发apicloud模块遇到的几个梗
    Android相关概念
    file-downloader相关问题
    Android 线程
    Android Studio Tip of the Day
    NAudio的使用说明
    IT回忆录-2
    IT回忆录-1
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13822666.html
Copyright © 2020-2023  润新知