线段树(区间合并)

题目:https://hihocoder.com/problemset/problem/1116

 

描述

现在有一个有n个元素的数组a1, a2, ..., an。

记f(i, j) = ai * ai+1 * ... * aj。

初始时,a1 = a2 = ... = an = 0,每次我会修改一个ai的值,你需要实时反馈给我 ∑1 <= i <= j <= n f(i, j)的值 mod 10007。

输入

第一行包含两个数n(1<=n<=100000)和q(1<=q<=500000)。

接下来q行,每行包含两个数i, x,代表我把ai的值改为了x。

输出

分别输出对应的答案,一个答案占一行。

样例输入

5 5
1 1
2 1
3 1
4 1
5 1

样例输出

1
3
6
10
15

题意:

        求区间(1,n)的所有子区间的连乘的和;

思路:

     线段数,这题如果用用线段树做不会的会可能就是不会合并两个区间;

      对于线段树的每一个节点,我们保持这个区间的答案(ans),前缀连乘和(ls),后缀连乘和,以及连乘(mul);

      对于每个节点我们可以这样合并:

至于为什么可以这样,自己举两三个数来看一看就很清楚了;

#include<bits/stdc++.h>
using namespace std;

#define mod 10007
const int maxn = 100 * 1000 + 10;

int n,q;
struct {
	struct {
		int L, R;
		int ls, rs, mul, ans;
	}tree[maxn<<2];
	void join(int rt) {
		tree[rt].ans = (tree[rt << 1].ans + tree[rt << 1 | 1].ans + tree[rt << 1].rs*tree[rt << 1 | 1].ls) % mod;
		tree[rt].ls = (tree[rt<<1].ls + tree[rt << 1].mul*tree[rt << 1 | 1].ls) % mod;
		tree[rt].rs = (tree[rt<<1|1].rs + tree[rt << 1|1].mul*tree[rt << 1].rs) % mod;
		tree[rt].mul = (tree[rt << 1].mul*tree[rt<<1|1].mul)%mod;
	}

	void build(int s,int L,int R) {
		tree[s].L = L; tree[s].R = R;
		tree[s].ls = tree[s].rs = tree[s].ans = tree[s].ans = 0;
		if (L == R)return;

		int mid = (L + R)>>1;
		build(s<<1,L,mid);
		build(s<<1|1,mid+1,R);
	}

	void change(int rt, int pos,int x) {
		if (tree[rt].L==tree[rt].R) {
			tree[rt].ls = tree[rt].rs = tree[rt].mul = tree[rt].ans = x;
			return;
		}

		int mid = (tree[rt].L + tree[rt].R) >> 1;
		if (pos <= mid)change(rt<<1,pos,x);
		else change(rt << 1 | 1, pos, x);

		join(rt);
	}

}T;

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> q;
	int p, x;
	T.build(1,1,n);
	while (q--) {
		cin >> p >> x;
		T.change(1,p,x);
		cout << T.tree[1].ans<<endl;
	}

	return 0;
}

 

全部评论

相关推荐

先记录一下前两次面试的经历bg:211本第一次(微众银行)6月初的时候面了微众银行,第一次面试,没准备好,八股很多都不会,出了一道多线程判断i++的题没做出来(问我加volatile是不是就可以了,我回答是),后面又问了Spring和Linux的内容,也是一点没答出来,面完后觉得应该没戏了就开摆准备期末考试了,谁知道一个星期后发了二面,于是火速学习Spring和Linux的八股,也没背多少,就准备了核心的几个(Springboot自动装配原理),刚好问到了,结束后问什么时候出结果,面试官说很快,觉得应该稳了,毕竟自己答的挺好的,3天后就约hr面了,其实当时就该注意到的,前两次hr小姐姐约面的时候声音听起来很温柔,约hr面的时候明显不开心,本来都打算租深圳的房子了,结果hr面的时候男hr说我投的是转正实习,不要26届。第一次面试遗憾结束第二次面试(字节跳动)距离微众hr面还有20min开始的时候字节hr打电话过来约面,当时都想拒掉了,一个是自己实在太菜,而且字节又比较重算法,肯定没戏,但是又觉得自己暑假已经有去处了所以觉得无所谓,就约了第二天下午,面试官出的题是我仅有的三次面试中最简单的了,真的很给机会了,leetcodehot两道中等难度的,出的八股也是基础中的基础,可惜算法只写出来一道,操作系统答的一坨,两天后发了感谢信第三次面试(美团)面完字节后就打算沉淀了,知道了自己很菜,算法不行,很多八股也没背(操作系统,spring全家桶,Linux)而且技术栈也不多,微服务,消息队列,Docker这些都不会,一直等到期末考试完开始小学期的时候,本来是准备一边参加学校实训一边沉淀的,结果小学期第一天上午美团发了面试申请,美团好像没有面评,就直接去面了,但是因为一直在复习期末考试,水平一直在原地踏步,算法还更差了(考试周一道leetcode没刷),感觉不太可能能过,所以干脆把自己会的好好复习下好了,结果面试官问的都是Java基础,全是送分题,出的算法还是二叉树层序遍历,反问的时候问有几轮技术面,结果居然只有一轮,问学习建议,面试官笑着说唯一的建议就是早点进入大厂做做项目,问多久出结果面试官也说很快,结果四个小时后hr就联系发口头offer了感觉日常实习大家的水平应该都是够的,就是看能不能约到面试,希望大家都能找到自己喜欢的实习,我先去喝开水了
查看14道真题和解析
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务