首页 > 其他分享 >P1438 无聊的数列

P1438 无聊的数列

时间:2024-04-03 19:45:30浏览次数:19  
标签:opt 数列 无聊 tree long int 区间 root P1438

题目大意
对于一个区间有两种操作,给一段区间加上一个等差数列,查询一个点的值,区间修改,单点查询,数据范围适当,显然,可以用线段树。
当进行第一种操作时,\(a[l] + k, a[l + 1] + k + d, a[l + 2] + k + d * 2 ... a[r] + k + d * (r - l)\),很明显一段区间内的每个数据所加的值并不相同,这就违背了线段树在一次给每个数据加上相同值的条件,所以,我们需要思考,如何避免这一问题,给连续一段区间加减,有一种简易手段,差分,因此只要将原数组差分一遍,给差分数组的区间内数据加值即可,求前缀和时,就会累计前面加的\(d\),因此区间修改时,干三件事即可。

update(1, 1, n, l, l, k);
if(l + 1 <= r) update(1, 1, n, l + 1, r, d);
if(r < n) update(1, 1, n, r + 1, r + 1, -(k + (r - l) * d));

这里有一个很重要的点,在后两条更新的语句执行前,一定要判一下边界,以防越界,不判的话,只有\(82pts\)。
代码如下

#include <iostream>
#include <cstdio>
using namespace std;
int n, m;
const int maxn = 1e5 + 5;
int a[maxn];
struct segment_tree 
{
	int l, r;
	long long value;
	long long tag;
};
segment_tree tree[maxn * 4];
void pushup(int root)
{
	tree[root].value = tree[root << 1].value + tree[(root << 1) + 1].value;
}
void build(int root, int l, int  r)
{
	tree[root].tag = 0ll;
	tree[root].l = l, tree[root].r = r;
	if (l == r)
	{
		tree[root].value = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(root << 1, l, mid);
	build((root << 1) + 1, mid + 1, r);
	pushup(root);
}
void pushdown(int root)
{	
	int l = tree[root].l, r = tree[root].r;
	int mid = (l + r) >> 1;
	tree[root << 1].tag += tree[root].tag;
	tree[(root << 1) + 1].tag += tree[root].tag;
	tree[root << 1].value += (mid - l + 1) * tree[root].tag;
	tree[(root << 1) + 1].value += (r - mid) * tree[root].tag;
	tree[root].tag = 0ll;
}
void update(int root, int l, int r, int L, int R, long long x)
{
	if (L <= l && r <= R)
	{
		tree[root].tag += x;
		tree[root].value += (r - l + 1) * x;
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(root);
	if(L <= mid) update(root << 1, l, mid, L, R, x);
	if(R > mid) update((root << 1) + 1, mid + 1, r, L, R, x);
	pushup(root);
	return;
}
long long query(int root, int l, int r, int L, int R)
{
	if(L <= l && r <= R) return tree[root].value;
	pushdown(root);
	int mid = (l + r) >> 1;
	long long res = 0ll;
	if(L <= mid) res += query(root << 1, l, mid, L, R);
	if(R > mid) res += query((root << 1) + 1, mid + 1, r, L, R);
	return res;
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(int i = n; i >= 1; i--) a[i] = a[i] - a[i - 1];
	build(1, 1, n);
	while (m--)
	{
		int opt;
		scanf("%d", &opt);
		if (opt == 1)
		{
			int l, r;
			long long k, d;
			scanf("%d%d%lld%lld", &l, &r, &k, &d);
			update(1, 1, n, l, l, k);
			if(l + 1 <= r) update(1, 1, n, l + 1, r, d);
			if(r < n) update(1, 1, n, r + 1, r + 1, -(k + (r - l) * d));
		}
		else
		{
			int p;
			scanf("%d", &p);
			printf("%lld\n", query(1, 1, n, 1, p));
		}
	}
	return 0;
} 

标签:opt,数列,无聊,tree,long,int,区间,root,P1438
From: https://www.cnblogs.com/coder2023/p/18113399

相关文章

  • 第十四届省赛大学B组(C/C++)接龙数列
    题目链接:接龙数列对于一个长度为 K 的整数数列:A1,A2,...,AK我们称之为接龙数列当且仅当 Ai 的首位数字恰好等于 Ai−1的末位数字(2≤i≤K)。例如 12,23,35,56,61,1112,23,35,56,61,11 是接龙数列;12,23,34,5612,23,34,56 不是接龙数列,因为 56 的首位数字不等于 3......
  • 蓝桥杯2019年第十三届省赛真题-数列求值
    一、题目数列求值【问题描述】给定数列1,1,1,3,5,9,17,…,从第4项开始,每项都是前3项的和。求第20190324项的最后4位数字。【答案提交】这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个4位整数(提示:答案的千位不为0),在提交答案时只填......
  • L1-080 乘法口诀数列
    注:考虑两个数字乘积是0的情况。#include<bits/stdc++.h>usingnamespacestd;intres[10000];intmain(){ inta,b,c; cin>>a>>b>>c; res[0]=a; res[1]=b; intpos=2; for(inti=0;;i++){ intans=res[i]*res[i+1]; vec......
  • 蓝桥杯 试题 基础练习 数列特征
    问题描述给出n个数,找出这n个数的最大值,最小值,和。输入格式第一行为整数n,表示数的个数。第二行有n个数,为给定的n个数,每个数的绝对值都小于10000。输出格式输出三行,每行一个整数。第一行表示这些数中的最大值,第二行表示这些数中的最小值,第三行表示这些数的和。样例输入5......
  • 以下是一个简单的C++程序,用于生成斐波那契数列的前n项
    斐波那契数列是一个在自然界中广泛出现的数列,其定义是:第一个和第二个数都是1,从第三个数开始,每一个数都是前两个数之和。斐波那契数列的前几项是:1,1,2,3,5,8,13,21,34,55,…以下是一个简单的C++程序,用于生成斐波那契数列的前n项:#include<iostream>#include<ve......
  • Fibonacci数列
    1.Fibonacci数列-蓝桥云课(lanqiao.cn)题目描述:Fibonacci数列:第1、2项均为1,从第3项开始,每一项都是前两项之和。输入n值,输出Fibonacci数列第n项,该数列前10项为1,1,2,3,5,8,13,21,34,55。输入描述:输入占一行,为n的值,1sns40。输出描述:输出占一行,为Fibonacci数列第n项......
  • 每日一练:LeeCode-38、外观数列【字符串】
    给定一个正整数n,输出外观数列的第n项。「外观数列」是一个整数序列,从数字1开始,序列中的每一项都是对前一项的描述。你可以将其视作是由递归公式定义的数字字符串序列:countAndSay(1)="1"countAndSay(n)是对countAndSay(n-1)的描述,然后转换成另一个数字字符串。......
  • 接龙数列
    @目录一、题目描述二、算法简析三、本题代码一、题目描述P9242[蓝桥杯2023省B]接龙数列二、算法简析核心思想:动态规划题目要我们求删除数的最小个数。可以转变问题,求能形成的接龙数列的最大长度\(MaxLength\),\(n-MaxLength\)即为所求。由题意可知,我们只需要关注每......
  • 泰波纳契数列
    实现泰波纳契数列的时候,用寻常的写法效率很低,classSolution:deftribonacci(self,n:int)->int:dp=[0foriinrange(n+1)]iflen(dp)==1:return0eliflen(dp)==2orlen(dp)==3:return1else......
  • 波动数列
    一、题目描述P8614[蓝桥杯2014省A]波动数列二、问题简析设第一个数为\(x_0\),\(d_i=a~or~-b\),则长度为\(n\)的数列的和为:\[\begin{split}s&=x_0+x_1+x_2+...+x_{n-1}\\&=(x_0+0)+(x_0+d_1)+(x_0+d_1+d_2)+...+(x_0+d_1+...+d_{n-1})\\&=n*x_0+0+(n-1)*d_1+(n-......