zoukankan      html  css  js  c++  java
  • 计蒜客信息学赛前CSP-S2模拟赛2 T4 平均数

    问题描述

    有一个长度为 n* 的序列,求所有长度大于等于 m 的子区间的平均数的最大值。

    还有 q 次单点加操作,每次操作后输出长度大于等于 m 的子区间的平均数的最大值。

    输入格式

    第一行三个正整数 (n,M,q),其中 (Mgeq) 所有询问的 (m) 值。

    第二行 (n) 个整数表示该序列。

    下面 (q) 行每行三个正整数 (x,c,m),表示将位置 (x)(c) 之后,长度大于等于 m 的子区间的平均数的最大值。

    输出格式

    输出 (q) 行,第 (i) 行输出两个正整数 (X,Y),表示平均数的最大值为 (X/Y)。((X/Y) 是最简分数)

    数据范围

    (1le nle 125000,mle min(50,n),qle 20000,a_i,c_ile 10^9)

    解析

    对于一个询问,最后选择的区间长度不会超过 (2m) 。因为超过 (2m) 的区间我们一定可以把它划分为两个区间,满足这两个区间有一个的平均数大于原区间。

    因此,我们不妨维护 (2M) 个线段树,第 (k) 个线段树中维护序列第 (i) 位开始的长度为 (k) 的区间和。单点加操作就是线段树区间修改。对于每一个询问,我们只需要查询第 (m) 到第 (2m-1) 棵线段树的最小值,然后更新答案即可。

    实际上我们不需要同时维护 (2M) 个线段树。我们可以把询问离线下来,然后枚举长度并依次维护第 (1) 到第 (2M) 棵线段树。每棵线段树都更新一下所有能够更新的询问。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define N 125002
    using namespace std;
    const double eps=1e-8;
    struct query{
    	int x,c,m;
    }q[N];
    struct SegmentTree{
    	long long dat,add;
    }t[N*4];
    int n,m,p,i,l,a[N],ansy[N];
    long long sum[N],ansx[N];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    void spread(int p)
    {
    	if(t[p].add){
    		t[p*2].dat+=t[p].add;t[p*2+1].dat+=t[p].add;
    		t[p*2].add+=t[p].add;t[p*2+1].add+=t[p].add;
    		t[p].add=0;
    	}
    }
    void build(int p,int l,int r,int x)
    {
    	t[p].dat=t[p].add=0;
    	if(l==r){
    		t[p].dat=sum[l+x-1]-sum[l-1];
    		return;
    	}
    	int mid=(l+r)/2;
    	build(p*2,l,mid,x);build(p*2+1,mid+1,r,x);
    	t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    void change(int p,int l,int r,int ql,int qr,int x)
    {
    	if(ql>qr) return;
    	if(ql<=l&&r<=qr){
    		t[p].dat+=x;t[p].add+=x;
    		return;
    	}
    	int mid=(l+r)/2;
    	spread(p);
    	if(ql<=mid) change(p*2,l,mid,ql,qr,x);
    	if(qr>mid) change(p*2+1,mid+1,r,ql,qr,x);
    	t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    int gcd(int a,int b)
    {
    	if(!b) return a;
    	return gcd(b,a%b);
    }
    signed main()
    {
    	freopen("average.in","r",stdin);
    	freopen("average.out","w",stdout);
    	n=read();m=read();p=read();
    	for(i=1;i<=n;i++) a[i]=read();
    	for(i=1;i<=p;i++) q[i].x=read(),q[i].c=read(),q[i].m=read();
    	for(i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
    	for(l=1;l<=min(2*m-1,n);l++){
    		build(1,1,n-l+1,l);
    		for(i=1;i<=p;i++){
    			int L=max(1,q[i].x-l+1),R=min(n-l+1,q[i].x);
    			change(1,1,n-l+1,L,R,q[i].c);
    			if(l>=q[i].m&&l<2*q[i].m){
     				if(ansy[i]==0||(long double)t[1].dat/l-(long double)ansx[i]/ansy[i]>eps) ansx[i]=t[1].dat,ansy[i]=l;
    			}
    		}
    	}
    	for(i=1;i<=p;i++){
    		int d=gcd(ansx[i]%ansy[i],ansy[i]);
    		printf("%lld %d
    ",ansx[i]/d,ansy[i]/d);
    	}
    	return 0;
    }
    
  • 相关阅读:
    克服 iOS HTML5 音频的局限
    oracle__删除重复记录__三种方法及总结(转载百度文库)
    Oracle 字符集
    无法通过网页进入em
    Ubuntu 12.04(32位)安装Oracle 11g(32位)全过程以及几乎所有问题的解决办法
    正则表达式30分钟入门教程
    linux下安装jdk
    QTP相关书籍
    假的数论gcd,真的记忆化搜索(Codeforce 1070- A. Find a Number)
    搜索基础_HDU1312_dfs_递归+stack实现+bfs_queue实现
  • 原文地址:https://www.cnblogs.com/LSlzf/p/13912336.html
Copyright © 2011-2022 走看看