首页 > 其他分享 >【题解】 P2221 [HAOI2012]高速公路

【题解】 P2221 [HAOI2012]高速公路

时间:2023-06-08 09:47:10浏览次数:52  
标签:rs int 题解 sum mid times ls HAOI2012 P2221

传送门

输入时将 \(r\) 先减 1。
发现收费之和为 $$ans = \sum\limits_{i = l} ^ {r} a_i \times (r - l + 1) \times (i - l + 1 )$$
化简得

\[ans = \sum\limits_{i = l} ^ {r} a_i \times (-i^2 + i \times (r + l) + (r - r \times l - l + 1)) \]

发现可以用线段树来维护:
\(sum1\) 表示 \(\sum\limits_{i = l}^{r} a_i\)
\(sum2\) 表示 \(\sum\limits_{i = l}^{r} a_i \times i\)
\(sum3\) 表示 \(\sum\limits_{i = l}^{r} a_i \times i ^ 2\)

发现区间修改时 \(sum2\) 和 \(sum3\) 不好维护。

引入 \(sum4\) 表示 \(\sum i\), \(sum5\) 表示 \(\sum i ^ 2\)

答案显然为 \(\dfrac{2 \times ans}{(r - l + 2) \times (r - l + 1)}\)。

#include<bits/stdc++.h>
#define int long long
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
const int N = 1e5 + 67;
int read(){
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -f; ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return x * f;
}
int n, m;
int sum1, sum2, sum3;
int sum[6][N << 2], lazy[N << 2];
void pushdown(int u, int l, int r){
	if(!lazy[u]) return ;
	lazy[ls] += lazy[u], lazy[rs] += lazy[u];
	int mid = (l + r) >> 1;
	sum[1][ls] += (mid - l + 1) * lazy[u], sum[1][rs] += (r - mid) * lazy[u];
	sum[2][ls] += sum[4][ls] * lazy[u], sum[2][rs] += sum[4][rs] * lazy[u];
	sum[3][ls] += sum[5][ls] * lazy[u], sum[3][rs] += sum[5][rs] * lazy[u];
	lazy[u] = 0;
}
void modify(int u, int l, int r, int L, int R, int v){
	if(L <= l && r <= R) return lazy[u] += v, sum[1][u] += (r - l + 1) * v, sum[2][u] += sum[4][u] * v, sum[3][u] += sum[5][u] * v, void();
	int mid = (l + r) >> 1;
	pushdown(u, l, r);
	if(L <= mid) modify(ls, l, mid, L, R, v);
	if(R > mid) modify(rs, mid + 1, r, L, R, v);
	sum[1][u] = sum[1][ls] + sum[1][rs], sum[2][u] = sum[2][ls] + sum[2][rs], sum[3][u] = sum[3][ls] + sum[3][rs];
}
void query(int u, int l, int r, int L, int R){
	if(L <= l && r <= R) return sum1 += sum[1][u], sum2 += sum[2][u], sum3 += sum[3][u], void();
	int mid = (l + r) >> 1;
	pushdown(u, l, r);
	if(L <= mid) query(ls, l, mid, L, R);
	if(R > mid) query(rs, mid + 1, r, L, R);
}
void build(int u, int l, int r){
	if(l == r) return sum[4][u] = l, sum[5][u] = l * l, void();
	int mid = (l + r) >> 1;
	build(ls, l, mid), build(rs, mid + 1, r);
	sum[4][u] = sum[4][ls] + sum[4][rs], sum[5][u] = sum[5][ls] + sum[5][rs]; 
}
int gcd(int a, int b){
	if(!b) return a;
	return gcd(b, a % b);
}
signed main(){
	n = read(), m = read();
	build(1, 1, n);
	while(m--){
		char opt[5]; scanf("%s", opt + 1);
		int l = read(), r = read() - 1;
		if(opt[1] == 'C'){
			int v = read();
			modify(1, 1, n, l, r, v);
		}else{
			if(l > r){
				printf("0/1\n");
				continue;
			} 
			sum1 = sum2 = sum3 = 0;
			query(1, 1, n, l, r);
			int r1 = (r - r * l - l + 1) * sum1 + (r + l) * sum2 - sum3;
			int r2 = (r - l + 2) * (r - l + 1) / 2;
			int t = gcd(r1, r2);
			printf("%lld/%lld\n", r1 / t, r2 / t);
		}
	}
	return 0;
} 

标签:rs,int,题解,sum,mid,times,ls,HAOI2012,P2221
From: https://www.cnblogs.com/jiangchen4122/p/17465261.html

相关文章

  • Codeforces Round 876 (Div. 2) 题解 A - D
    A.TheGoodArray题目大意给定两个整数\(n\)和\(k\),规定一个\(01\)数列为好的的条件是,对于\(1\simn\)中任意的\(i\),都有:\(a\)的前\(i\)个元素中至少有\(\lceil\frac{i}k\rceil\)个都是\(1\)。\(a\)的后\(i\)个元素中至少有\(\lceil\frac{i}k\rceil\)个都是......
  • 题解:【ARC142D】 Deterministic Placing
    题目链接大佬讲解的太精简了,做点蒟蒻视角的思考补充。下面记摆放棋子的点为黑点,没有摆放棋子的为白点。因为进行无数次操作后,占据节点集合总是唯一,所以黑点一定是在反复横跳;每个位置上只能存在一个黑点,所以每次把移动黑点经过的边拿出来,得到的是若干条不相交的链,并且这些链一定......
  • ABC300F 题解
    前两天忘发出来了,补一下QAQ题目链接题意简述给定一个长度为\(n\)且只包含\(\texttt{o}\)和\(\texttt{x}\)的字符串\(s\)以及正整数\(n\)\(m\)\(k\),令字符串\(T=s^{m}\),求将\(T\)中的\(k\)个\(\texttt{x}\)变成\(\texttt{o}\)之后,\(T\)中连续\(\texttt{o}......
  • P3392 涂国旗 题解
    题目大意题目真的是不说人话......有一个国家的国旗是由一个N*M的方格组成的。如果想要这面国旗合法,就必须满足要求:国旗从上到下必须是白色、蓝色和红色,顺序不能改变。每一种颜色都至少有一行。小a这时候捡到了一块破布,希望你通过涂颜色的方式,把破布成合法的国旗,并且要......
  • 题解 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
    传送门如题目所言,这就是个线段树合并的板子题。题目大意题目描述首先村落里的一共有\(n\)座房屋,并形成一个树状结构。然后救济粮分\(m\)次发放,每次选择两个房屋\((x,y)\),然后对于\(x\)到\(y\)的路径上(含\(x\)和\(y\))每座房子里发放一袋\(z\)类型的救济粮。然......
  • 【每日一题】LeetCode 786. 第K个最小的素数分数(待补全题解思路)
    题目给你一个按递增顺序排序的数组arr和一个整数k。数组arr由1和若干素数组成,且其中所有整数互不相同。对于每对满足0<i<j<arr.length的i和j,可以得到分数arr[i]/arr[j]。那么第k个最小的分数是多少呢?以长度为2的整数数组返回你的答案,这里answer......
  • 2023上半年(下午)网络工程师试题解析
    2023上半年(下午)网络工程师试题解析试题一(20分)某企业办公楼网络拓扑如图1-1所示。该网络中交换机Switch1-Switch4均是二层设备,分布在办公楼的各层,上联采用千兆光纤。核心交换机、防火墙、服务器部署在数据机房,其中核心交换机实现冗余配置。图1-1问题1(4分)该企业办公网络采用172.16.1......
  • CF1559D2 Mocha and Diana (Hard Version) 题解
    Luogu|Codeforces题意给定两个森林\(A\)和\(B\),均有编号\(1\)到\(n\)的节点,边数分别为\(m_1,m_2\)。现在进行加边操作,但是有两个要求:如果在第一个森林加一条\((u,v)\)的边,第二个森林也要进行同样的操作。反之同理。加边后两个森林依旧是森林。一棵树也是森林。......
  • 应用问题解决-分布式锁(LUA保证删除原子性)
    问题:删除操作缺乏原子性场景1、index1获得锁、执行具体操作、比较lock的uuid值确实和自己生成的uuid是否相等,相等则删除锁。uuid=v1set(lock,uuid)uuid.equals(get("lock"))2、但是index1执行删除前,lock刚好过期时间已经到了,被redis自动释放3、此时index2获取锁,执行具体......
  • 在centos7升级nodejs存在的无法切换版本的问题解决
    1.安装n管理工具npminstall-gn安装最新版本nlatest安装指定版本 n8.11.3 2.切换nodejs版本n选择已安装的版本 ο node/8.11.3  node/10.4.1查看当前版本node-v,下面表示已切换成功v8.13.3但问题来了,切换后,查看版本还是原来的v6.13.3,看下面 使用n切换nodejs......