[HAOI2012]高速公路

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Stevencwehf/article/details/102665763

题目
Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站。
Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。
政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。
无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l< r),在第l个到第r个收费站里等概率随机取出两个不同的收费站a和b,那么从a行驶到b将期望花费多少费用呢?

第一行2个正整数N,M,表示有N个收费站,M次调整或询问
接下来M行,每行将出现以下两种形式中的一种
C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加v
Q l r 表示对于给定的l,r,要求回答小A的问题
所有C与Q操作中保证1<=l<r<=N

这道题很明显的线段树 但是维护方法不是那么好想
首先将式子列出
在这里插入图片描述

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define lc (p<<1)
#define rc (p<<1|1)
inline int read()
{
    int data=0;int w=1; char ch=0;
    ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return data*w;
}
const int N=111000;
int n,m,sum1,sum2,sum3;
char op[5];
int  gcd(int a,int b){if(b==0) return a;return gcd(b,a%b);}
struct node{
	int l,r,lazy;
	int sum[6];
}t[N<<2];
inline void work(int p,int k){
	t[p].sum[1]+=(t[p].r-t[p].l+1)*k;
	t[p].sum[2]+=t[p].sum[4]*k;
	t[p].sum[3]+=t[p].sum[5]*k; 
	t[p].lazy+=k;
}
inline void pushup(int p){
	for(int i=1;i<=3;i++){
		t[p].sum[i]=t[lc].sum[i]+t[rc].sum[i];
	} 
}
inline void pushdown(int p){
	if(t[p].lazy){
		work(lc,t[p].lazy);work(rc,t[p].lazy);
	}
	t[p].lazy=0;
}
inline void build(int p,int l,int r){
	t[p].l=l;t[p].r=r;
	if(l==r){
		t[p].sum[4]=l;t[p].sum[5]=l*l;return; 
	}
	int mid=(l+r)>>1;
	build(lc,l,mid);build(rc,mid+1,r);
	t[p].sum[4]=t[lc].sum[4]+t[rc].sum[4];
	t[p].sum[5]=t[lc].sum[5]+t[rc].sum[5];
}
inline void modify(int p,int L,int R,int k){
	int l=t[p].l,r=t[p].r;
	if(l>=L&&r<=R){
		work(p,k);return;
	} 
	pushdown(p);
	int mid=(l+r)>>1;
	if(L<=mid) modify(lc,L,R,k);
	if(R>mid) modify(rc,L,R,k);
	pushup(p); 
} 
inline void query(int p,int L,int R){
	int l=t[p].l,r=t[p].r;
	if(l>=L&&r<=R){
	     sum1+=t[p].sum[1];
	     sum2+=t[p].sum[2];
	     sum3+=t[p].sum[3];
		 return;
	}
	pushdown(p);
	int mid=(l+r)>>1;
	if(L<=mid) query(lc,L,R);
	if(R>mid) query(rc,L,R);
}
signed main(){
	n=read();m=read();
	build(1,1,n);
    while(m--){
		scanf("%s",op);
		if(op[0]=='C') {
			int l=read(),r=read()-1,v=read();
			modify(1,l,r,v);
		}
		else{
			int l=read(),r=read()-1;
			int a,b,g;
		    sum1=0;sum2=0;sum3=0;
		    query(1,l,r);
		    a=(r-l+1-r*l)*sum1+(r+l)*sum2-sum3;
		    b=(r-l+2)*(r-l+1)/2;
		    g=gcd(a,b);
		    printf("%lld/%lld\n",a/g,b/g);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Stevencwehf/article/details/102665763