poj-3468 区间操作

http://poj.org/problem?id=3468

区间求和操作 ,一个区间加操作。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <iomanip>

using namespace std;

#define ll(ind) (ind<<1)
#define rr(ind) (ind<<1|1)
#define Mid(a,b) (a+((b-a)>>1))

typedef __int64 LL;

const int N = 100100;

int a[N];

struct node
{
	int left, right;
	LL sum, lazy;;
	int mid()
	{
		return Mid(left, right);
	}

	void fun(LL summ)
	{
		lazy += summ;
		sum += (right - left + 1) * summ;
	}
};

struct segtree
{
	node tree[N * 4];

	void real(int ind)//更新懒惰标记
	{
		if (tree[ind].lazy)
		{
			tree[ll(ind)].fun(tree[ind].lazy);
			tree[rr(ind)].fun(tree[ind].lazy);
			tree[ind].lazy = 0;
		}
	}

	void buildtree(int left, int right, int ind)//建树
	{
		tree[ind].left = left;
		tree[ind].right = right;
		tree[ind].sum = 0;
		tree[ind].lazy = 0;

		if (left == right)
		{
			tree[ind].sum = a[left];
		}

		if (left != right)
		{
			int mid = tree[ind].mid();
			buildtree(left, mid, ll(ind));
			buildtree(mid + 1, right, rr(ind));
			tree[ind].sum = tree[ll(ind)].sum + tree[rr(ind)].sum;
		}
	}

	void update(int st, int ed, int ind, int type)//更新
	{
		int left = tree[ind].left;
		int right = tree[ind].right;

		if (st <= left && right <= ed)
			tree[ind].fun(type);

		else
		{
			real(ind);

			int mid = tree[ind].mid();
			if (st <= mid) update(st, ed, ll(ind), type);
			if (ed > mid) update(st, ed, rr(ind), type);
			tree[ind].sum = tree[ll(ind)].sum + tree[rr(ind)].sum;
		}
	}

	LL query(int st, int ed, int ind)//求和
	{
		int left = tree[ind].left;
		int right = tree[ind].right;

		if (st <= left && right <= ed)
			return tree[ind].sum;
		else
		{
			real(ind);
			int mid = tree[ind].mid();

			LL s1 = 0, s2 = 0;
			if (st <= mid)
				s1 = query(st, ed, ll(ind));
			if (ed > mid)
				s2 = query(st, ed, rr(ind));

			return s1 + s2;
		}
	}
}seg;

int main()
{
	int n, m;
	int x, y, z;

	while (scanf("%d %d", &n, &m) != EOF)
	{
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);

		seg.buildtree(1, n, 1);

		char d[5];

		while (m--)
		{
			scanf("%s", d);
			if (d[0] == 'Q')
			{
				scanf("%d %d", &x, &y);
				cout << seg.query(x, y, 1) << endl;

			}
			else
			{
				scanf("%d %d %d", &x, &y, &z);
				seg.update(x, y, 1, z);
			}
		}
	}
	return 0;
}
时间: 2024-08-06 13:00:23

poj-3468 区间操作的相关文章

POJ 3468 区间更新,区间求和(经典)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 72265   Accepted: 22299 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ 3468 区间更新(求任意区间和)A Simple Problem with Integers

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 163977   Accepted: 50540 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o

POJ 3468 区间加减 区间求和

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 #define INF 0x7fffffff 8 #define maxn 101000 9 #define LL long long 10 using name

A Simple Problem with Integers POJ - 3468 区间更新,区间查询板子

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<list> #include<math.h> #include<vector> #include<stack>

poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)

题目链接:http://poj.org/problem?id=3468 题解:splay功能比线段树强大当然代价就是有些操作比线段树慢,这题用splay实现的比线段树慢上一倍.线段树用lazy标记差不多要2s用splay要4s.可以用splay来实现线段树的区间操作更深层次的了解一下splay算是入个门. #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #i

线段树 + 区间更新 + 模板 ---- poj 3468

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59798   Accepted: 18237 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 3225 区间(区间的交并补操作)

http://poj.org/problem?id=3225 一道题又做了一天..这道题对我来说起初有N多难点. 1:区间的开闭如何解决.. 2:怎样把区间的交并补.对称差转化为对线段树的操作. 后来与实验室的同学讨论了后解决了前面两个问题. 对于区间的开闭,可以将区间放大一倍,偶数点表示端点,奇数点表示区间内线段,前开的话左端点加1,右开的话右端点减1.例如[1,3]可以表示成[2,6],(1,3)表示成(3,5). 对于区间的交并补问题,可以转化为区间覆盖问题,若T区间为[a,b]. U T

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ - 3468 A Simple Problem with Integers (区间求和)

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In