洛谷P2122 还教室

题目背景

还记得 NOIP 2012 提高组 Day2 中的借教室吗?时光飞逝,光阴荏苒,两年

过去了,曾经借教室的同学们纷纷归还自己当初租借的教室。请你来解决类似于

借教室的另一个问题。

题目描述

在接受借教室请求的 n 天中,第 i 天剩余的教室为 ai个。作为大学借教室服

务的负责人,你需要完成如下三种操作共 m 次:

① 第 l 天到第 r 天,每天被归还 d 个教室。

② 询问第 l 天到第 r 天教室个数的平均数。

③ 询问第 l 天到第 r 天教室个数的方差。

输入输出格式

输入格式:

第一行包括两个正整数 n 和 m,其中 n 为借教室的天数,m 为操作次数。

接下来一行,共包含 n 个整数,第 i 个整数表示第 i 天剩余教室数目为 ai个。

接下来 m 行,每行的第一个整数为操作编号(只能为 1 或 2 或 3),接下来

包含两个正整数 l 和 r,若操作编号为 1,则接下来再包含一个正整数 d。

输出格式:

对于每个操作 2 和操作 3,输出一个既约分数(分子与分母互质)表示询问

的答案(详见样例)。若答案为 0,请输出“0/1”(不含引号)。

输入输出样例

输入样例#1: 
5 4
1 2 3 4 5
1 1 2 3
2 2 4
3 2 4
3 1 5
输出样例#1: 
4/1
2/3
14/25

说明

对于全部测试数据满足:1 ≤ l ≤ r ≤ n,0 ≤ ai ≤ 10,1 ≤ d ≤ 3,操作 1 的数量

不超过 10%。注意:ai和 d 的范围很小及操作 1 数量很少的原因是为了保证答案

的分子不会很大,以防止答案的分子溢出 64 位整数的范围,这与题目做法无关。

线段树裸题。。。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) a[x].data
#define MEXP(x) a[x].mexp
#define SIGN(x) a[x].c
#define LSIDE(x) a[x].l
#define RSIDE(x) a[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 100010
using namespace std;
int n,m;
struct node{
	long long data,c;
	unsigned long long mexp;
	int l,r;
}a[MAXN<<2];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
long long gcd(long long x,long long y){
	if(y==0)return x;
	return gcd(y,x%y);
}
inline void pushup(int rt){
	DATA(rt)=DATA(LSON)+DATA(RSON);
	MEXP(rt)=MEXP(LSON)+MEXP(RSON);
}
inline void pushdown(int rt){
	if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
	SIGN(LSON)+=SIGN(rt);
	MEXP(LSON)+=SIGN(rt)*SIGN(rt)*WIDTH(LSON)+2*SIGN(rt)*DATA(LSON);
	DATA(LSON)+=SIGN(rt)*WIDTH(LSON);
	SIGN(RSON)+=SIGN(rt);
	MEXP(RSON)+=SIGN(rt)*SIGN(rt)*WIDTH(RSON)+2*SIGN(rt)*DATA(RSON);
	DATA(RSON)+=SIGN(rt)*WIDTH(RSON);
	SIGN(rt)=0;
}
void buildtree(int l,int r,int rt){
	int mid;
	LSIDE(rt)=l;
	RSIDE(rt)=r;
	SIGN(rt)=0;
	if(l==r){
		DATA(rt)=read();
		MEXP(rt)=DATA(rt)*DATA(rt);
		return;
	}
	mid=l+r>>1;
	buildtree(l,mid,LSON);
	buildtree(mid+1,r,RSON);
	pushup(rt);
}
void update(int l,int r,long long c,int rt){
	int mid;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
		SIGN(rt)+=c;
		MEXP(rt)+=c*c*WIDTH(rt)+2*c*DATA(rt);
		DATA(rt)+=c*WIDTH(rt);
		return;
	}
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)update(l,r,c,LSON);
	if(mid<r)update(l,r,c,RSON);
	pushup(rt);
}
long long query_sum(int l,int r,int rt){
	int mid;
	long long ans=0;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
	return DATA(rt);
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)ans+=query_sum(l,r,LSON);
	if(mid<r)ans+=query_sum(l,r,RSON);
	return ans;
}
unsigned long long query_mexp(int l,int r,int rt){
	int mid;
	unsigned long long ans=0;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
	return MEXP(rt);
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)ans+=query_mexp(l,r,LSON);
	if(mid<r)ans+=query_mexp(l,r,RSON);
	return ans;
}
inline void single(long long &s1,long long &s2){
	long long k=gcd(s1,s2);
	s1/=k;s2/=k;
}
int main(){
	int f,x,y,k;
	n=read();m=read();
	buildtree(1,n,1);
	while(m--){
		f=read();x=read();y=read();
		switch(f){
			case 1:{
				k=read();
				update(x,y,k,1);
				break;
			}
			case 2:{
				long long s1=query_sum(x,y,1),s2=y-x+1;
				if(s1==0)s2=1;
				else single(s1,s2);
				printf("%lld/%lld\n",s1,s2);
				break;
			}
			case 3:{
				long long s1=query_sum(x,y,1),s2=query_mexp(x,y,1),s3=y-x+1,k;
				s2=s2*s3-s1*s1;s3*=s3;
				if(s2==0)s3=1;
				else single(s2,s3);
				printf("%lld/%lld\n",s2,s3);
				break;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值