Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code

题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,。。。或者从右到左加上。。。3,2,1 或者把某个区间的数都置为v

思路:我是加了6个域

add是这段区间每个数都要加上add  add是这么来的 对与123456。。。这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3

v是这个区间都要置为v 他的优先级最高

b是代表这个区间有多少个递增的等差数列

c是代表这个区间有多少个递减的等差数列

sum是区间和

f为真说明要执行C 因为v可以是正和负还可以是0

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 250010;
typedef long long LL;
struct node
{
	LL sum, add, v, b, c;
 	bool f;
}a[maxn<<2];

void build(int l, int r, int rt)
{
	a[rt].sum = 0;
	a[rt].add = 0;
	a[rt].b = 0;
	a[rt].c = 0;
	a[rt].f = false;
	if(l == r)
		return;
	int m = (l + r) >> 1;
	build(l, m, rt<<1);
	build(m+1, r, rt<<1|1);
}

void pushdown(int rt, int l, int r)
{
	LL k = (LL)(r-l+1);
	//printf("%d %d %lld\n", l, r, a[rt].v);
	if(a[rt].f)
	{
		a[rt<<1].sum = (LL)a[rt].v*(k-(k>>1));
		a[rt<<1|1].sum = (LL)a[rt].v*(k>>1);
		a[rt<<1].v = a[rt<<1|1].v = a[rt].v;
		a[rt<<1].f = a[rt<<1|1].f = true;
		a[rt].f = false;
		a[rt<<1].b = a[rt<<1|1].b = 0;
		a[rt<<1].c = a[rt<<1|1].c = 0;
		a[rt<<1].add = a[rt<<1|1].add = 0;

	}
	LL s1 = (k-(k>>1));
	LL s2 = (k>>1);
	if(a[rt].b)
	{
		a[rt<<1].sum += (LL)a[rt].b*(1+s1)*s1/2;
		a[rt<<1|1].sum += (LL)a[rt].b*(1+s2)*s2/2+(LL)s2*s1*a[rt].b;
		a[rt<<1].b += a[rt].b;
		a[rt<<1|1].b += a[rt].b;
		a[rt<<1|1].add += (LL)s1*a[rt].b;
		a[rt].b = 0;
	}
	if(a[rt].c)
	{
		a[rt<<1].sum += (LL)a[rt].c*(1+s1)*s1/2+(LL)s2*s1*a[rt].c;
		a[rt<<1|1].sum += (LL)a[rt].c*(1+s2)*s2/2;
		a[rt<<1].c += a[rt].c;
		a[rt<<1|1].c += a[rt].c;
		a[rt<<1].add += (LL)s2*a[rt].c;
		a[rt].c = 0;
	}
	if(a[rt].add)
	{
		a[rt<<1].sum += (LL)a[rt].add*(k-(k>>1));
		a[rt<<1|1].sum += (LL)a[rt].add*(k>>1);
		a[rt<<1].add += a[rt].add;
		a[rt<<1|1].add += a[rt].add;
		a[rt].add = 0;
	}
}
void update(int x, int y, int l, int r, int rt, LL add, LL v, char c)
{
	//puts("we");
	if(l == x && r == y)
	{
		if(c == 'A')
		{
			/*if(a[rt].f)
			{
				a[rt].sum = (LL)(r-l+1)*v;
				//a[rt].f = false;
			}*/
			a[rt].sum += (LL)(r-l+1)*(r-l+1+1)/2;
			a[rt].b++;
			a[rt].sum += (LL)add*(r-l+1);
			a[rt].add += add;
			//printf("%d %d %d %lld\n", l, r, a[rt].b, a[rt].sum);
		}
		else if(c == 'B')
		{
			/*if(a[rt].f)
			{
				a[rt].sum = (LL)(r-l+1)*v;
				//a[rt].f = false;
			}*/
			a[rt].sum += (LL)(r-l+1)*(r-l+1+1)/2;
			a[rt].c++;
			a[rt].sum += (LL)add*(r-l+1);
			a[rt].add += add;
		}
		else if(c == 'C')
		{
			a[rt].f = true;
			a[rt].add = 0;
			a[rt].sum = (LL)(r-l+1)*v;
			a[rt].b = 0;
			a[rt].c = 0;
			a[rt].v = v;

		}
		return;
	}
	int m = (l + r) >> 1;
	pushdown(rt, l, r);
	if(y <= m)
	{
		update(x, y, l, m, rt<<1, add, v, c);
	}
	else if(x > m)
	{
		update(x, y, m+1, r, rt<<1|1, add, v, c);
	}
	else
	{
		if(c == 'A')
		{
			update(x, m, l, m, rt<<1, add, v, c);
			update(m+1, y, m+1, r, rt<<1|1, add+(m-x+1), v, c);
		}
		else if(c == 'B')
		{
			update(x, m, l, m, rt<<1, add+(y-m), v, c);
			update(m+1, y, m+1, r, rt<<1|1, add, v, c);
		}
		else if(c == 'C')
		{
			//puts("as");
			update(x, m, l, m, rt<<1, add, v, c);
			update(m+1, y, m+1, r, rt<<1|1, add, v, c);
		}
	}
	a[rt].sum = a[rt<<1].sum + a[rt<<1|1].sum;

}

LL query(int x, int y, int l, int r, int rt)
{
	if(x == l && y == r)
	{
		//printf("**%d %d %lld\n", l, r, a[rt].sum);
		return a[rt].sum;
	}
	pushdown(rt, l, r);
	int m = (l + r) >> 1;
	LL ans = 0;
	if(y <= m)
		ans += query(x, y, l, m, rt<<1);
	else if(x > m)
		ans += query(x, y, m+1, r, rt<<1|1);
	else
		ans = query(x, m, l, m, rt<<1) + query(m+1, y, m+1, r, rt<<1|1);
	a[rt].sum = a[rt<<1].sum + a[rt<<1|1].sum;
	return ans;
}
int main()
{
	int cas = 1;
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n = 250000;
		int q;
		scanf("%d", &q);
		printf("Case %d:\n", cas++);
		build(1, n, 1);
		while(q--)
		{
			char s[10];
			scanf("%s", s);
			if(s[0] == 'A')
			{

				int x, y;
				scanf("%d %d", &x, &y);
				update(x, y, 1, n, 1, 0, 0, 'A');
			}
			else if(s[0] == 'B')
			{
				int x, y;
				scanf("%d %d", &x, &y);
				update(x, y, 1, n, 1, 0, 0, 'B');
			}
			else if(s[0] == 'C')
			{
				int x, y;
				LL w;
				scanf("%d %d %lld", &x, &y, &w);
				update(x, y, 1, n, 1, 0, w, 'C');
			}
			else
			{
				int x, y;
				scanf("%d %d", &x, &y);
				printf("%lld\n", query(x, y, 1, n, 1));
			}
		}

	}
	return 0;
}
/*
10
B 1 4
A 1 4
S 2 2
B 1 3
C 1 4 1
B 1 4
C 3 3 3
A 2 3
S 2 3
B 3 3
*/

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新,布布扣,bubuko.com

时间: 2024-12-28 19:36:32

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新的相关文章

uva 12436 - Rip Van Winkle&#39;s Code(线段树)

题目链接:uva 12436 - Rip Van Winkle's Code 题目大意:四种操作,操作见题目. 解题思路:即用线段树维护一个等差数列,因为一个等差加上一个等差还是一个等差数列,所以对于每个节点记录区 间左端的值,也就是首项,以及公差即可.因为还有一个S操作,所以要开一个标记记录区间值是否相同. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; ty

Uva 12436 Rip Van Winkle&#39;s Code

Rip Van Winkle was fed up with everything except programming. One day he found a problem whichrequired to perform three types of update operations (A, B, C), and one query operation S over an arraydata[]. Initially all elements of data are equal to 0

UVA-12436 Rip Van Winkle&#39;s Code (线段树区间更新)

题目大意:一个数组,四种操作: long long data[250001]; void A( int st, int nd ) { for( int i = st; i <= nd; i++ ) data[i] = data[i] + (i - st + 1); } void B( int st, int nd ) { for( int i = st; i <= nd; i++ ) data[i] = data[i] + (nd - i + 1); } void C( int st, int

UVA 12436 - Rip Van Winkle&#39;s Code(线段树)

UVA 12436 - Rip Van Winkle's Code 题目链接 题意:区间修改一个添加等差数列,一个把区间设为某个值,然后询问区间和 思路:关键在于等差数列的地方,线段树的每个结点添加一个首项和公差,由于等差数列加上一个等差数列还是一个等差数列,利用这个性质就可以进行维护了,注意set操作会覆盖掉等差数列的操作 代码: #include <cstdio> #include <cstring> #define lson(x) ((x<<1)+1) #defi

Light Switching(SPOJ LITE)—— 线段树成段更新异或值

题目连接:http://www.spoj.com/problems/LITE/en/. 题意:有若干个灯泡,每次对一段操作,这一段原先是亮的,就关了:原先是关着的,就打开.询问某一段的打开的灯泡的个数. 分析:很显然的成段更新,但是一开始想着用某段是不是相同的来维护,敲了很长时间都没有实现.后来经过大力学长知道,对有懒惰标记的节点的亮着的灯泡的和这么更新即可:c[o]=r-l+1-c[o]; 简直奥义! 另外,从这题可以看出,我对于成段更新的懒惰标记理解不够深刻.应该理解如下:对某点进行push

UVA 12436-Rip Van Winkle&#39;s Code(线段树的区间更新)

题意: long long data[250001]; void A( int st, int nd ) { for( int i = st; i \le nd; i++ ) data[i] = data[i] + (i - st + 1); } void B( int st, int nd ) { for( int i = st; i \le nd; i++ ) data[i] = data[i] + (nd - i + 1); } void C( int st, int nd, int x

light oj 1094 Farthest Nodes in a Tree(树的直径模板)

1094 - Farthest Nodes in a Tree PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Given a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undire

【USACO 2008 Nov Gold】 3.Light Switching(lites 开关灯) 区间修改线段树

题意: n.m,n个灯,m次操作 两种操作 0: 这段区间全部状态取反,初始全部为0 1: 询问这段区间有几个灯是亮的. 裸线段树,弱爆了. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 101000 #define inf 0x3f3f3f3f using namespace std; struct Segment_Tree {

Light OJ 1054 Efficient Pseudo Code 求n^m的约数和

题目来源:Light OJ 1054 Efficient Pseudo Code 题意:求n的m次这个数的所有的约数和 思路:首先对于一个数n = p1^a1*p2^a2*p3^a3*-*pk^ak  约束和s = (p1^0+p1^1+p1^2+-p1^a1)(p2^0+p2^1+p2^2+-p2^a2)-(pk^0+pk^1+pk^2+-pk^ak) 然后就是先求素数表 分解因子 然后求p1^0+p1^1+p1^2+-p1^a1 这是一个以1开始的等比数列 就是(1-q^n)/(1-q) 最