A Simple Problem with Integers OpenJ_Bailian - 3439

傳送門

這個主要用到一種方法:不是每次更新都要從根節點更新到葉子節點,更新到枝幹就行,在查找的時候在去處理

代碼:

#include<iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <functional>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <algorithm>
#define ll long long
#define mes(x,y) memset(x,y,sizeof(x))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
ll GCD(ll a, ll b) {//最大公約數
	return b == 0 ? a : GCD(b, a % b);
}
ll Power(ll a, ll b, ll p) { //計算(a^b)%p;
	ll ans = 1;
	while (b) {
		if (b & 1) //等價於b%2,判斷b的奇偶性
			ans = ans * a % p; //如果爲奇數,證明該位爲1,需要乘上a
		a = a * a % p; //計算a^(2^i)
		b >>= 1; //等價於b/=2;
	}
	return ans;
}
bool isprime(int num)
{
	if (num == 2 || num == 3)
		return true;
	if (num % 6 != 1 && num % 6 != 5)
		return false;
	int t = sqrt((double)num);
	for (int i = 5; i <= t; i += 6)
	{
		if (num % i == 0 || num % (i + 2) == 0)
			return false;
	}
	return true;
}
const ll INFF = 2000000;
struct node {
	ll begin = 0, end = 0, flag = 0;
	ll sum = 0, inc = 0;
	ll Mid1() {
		return ((begin + end) / 2);
	}
	ll Mid2() {
		return((begin + end) / 2 + 1);
	}
	ll Left() {
		return (flag * 2);
	}
	ll Right() {
		return (flag * 2 + 1);
	}
}tree[400010];
void BuildTree(ll flag, ll begin, ll end) {
	tree[flag].inc = tree[flag].sum = 0;
	tree[flag].begin = begin;
	tree[flag].end = end;
	tree[flag].flag = flag;
	//cout << flag << ":" << tree[flag].begin << " " << tree[flag].end << " " << tree[flag].Mid1() << endl;
	if (begin == end)return;
	BuildTree(tree[flag].Left(), begin, tree[flag].Mid1());
	BuildTree(tree[flag].Right(), tree[flag].Mid2(), end);
}
void Insert(ll flag, ll set, ll value) {
	if (tree[flag].begin == set && tree[flag].end == set) {
		tree[flag].sum = value;//重點
		return;
	}
	tree[flag].sum += value;//重點
	if (set <= tree[flag].Mid1()) {
		Insert(tree[flag].Left(), set, value);
	}
	else {
		Insert(tree[flag].Right(), set, value);
	}
}
void Add(ll flag, ll begin, ll end, ll value) {
	if (tree[flag].begin == begin && tree[flag].end == end) {
		tree[flag].inc += value;//重點
		return;
	}
	tree[flag].sum += (end - begin + 1) * value;//重點
	if (end <= tree[flag].Mid1()) {
		Add(tree[flag].Left(), begin, end, value);
	}
	else if (begin >= tree[flag].Mid2()) {
		Add(tree[flag].Right(), begin, end, value);
	}
	else {
		Add(tree[flag].Left(), begin, tree[flag].Mid1(), value);
		Add(tree[flag].Right(), tree[flag].Mid2(), end, value);
	}
}
ll Query(ll flag, ll begin, ll end) {
	if (tree[flag].begin == begin && tree[flag].end == end) {
		return tree[flag].sum + (end - begin + 1) * tree[flag].inc;
	}
	tree[flag].sum += (tree[flag].end - tree[flag].begin + 1) * tree[flag].inc;
	tree[tree[flag].Left()].inc += tree[flag].inc;
	tree[tree[flag].Right()].inc += tree[flag].inc;
	tree[flag].inc = 0;
	if (end <= tree[flag].Mid1()) {
		Query(tree[flag].Left(), begin, end);
	}
	else if (begin >= tree[flag].Mid2()) {
		Query(tree[flag].Right(), begin, end);
	}
	else {
		return Query(tree[flag].Left(), begin, tree[flag].Mid1())+ Query(tree[flag].Right(), tree[flag].Mid2(), end);
		
	}
}
int main() {
	//FAST_IO;
	ll n, m, k, i, j, vb;
	while (cin >> n >> m) {
		BuildTree(1, 1, n);
		for (i = 1; i <= n; i++) {
			cin >> j;
			Insert(1, i, j);
		}
		ll x, y,z;
		string a;
		for (i = 0; i < m; i++) {
			cin >> a;
			if (a == "Q") {
				cin >> x >> y;
				cout << Query(1, x, y) << endl;
			}
			else {
				cin >> x >> y >> z;
				Add(1, x, y, z);
			}
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章