UVA 12436 - Rip Van Winkle's Code(线段树)

简介:

UVA 12436 - Rip Van Winkle's Code

题目链接

题意:区间改动一个加入等差数列,一个把区间设为某个值,然后询问区间和

思路:关键在于等差数列的地方,线段树的每一个结点加入一个首项和公差,因为等差数列加上一个等差数列还是一个等差数列。利用这个性质就能够进行维护了,注意set操作会覆盖掉等差数列的操作

代码:

#include <cstdio>
#include <cstring>

#define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2)

typedef long long ll;
const int N = 250005;
int n;

struct Node {
	ll l, r, a1, d, c, val;
	int setc;
} node[N * 4];

void build(ll l, ll r, int x = 0) {
	node[x].l = l; node[x].r = r;
	node[x].a1 = node[x].d = node[x].val = node[x].setc = 0;
	if (l == r) return;
	ll mid = (l + r) / 2;
	build(l, mid, lson(x));
	build(mid + 1, r, rson(x));
}

void pushup(int x) {
	node[x].val = node[lson(x)].val + node[rson(x)].val;
}

void pushdown(int x) {
	if (node[x].setc) {
		node[lson(x)].c = node[rson(x)].c = node[x].c;
		node[lson(x)].val = (node[lson(x)].r - node[lson(x)].l + 1) * node[x].c;
		node[rson(x)].val = (node[rson(x)].r - node[rson(x)].l + 1) * node[x].c;
		node[lson(x)].setc = node[rson(x)].setc = 1;
		node[lson(x)].a1 = node[lson(x)].d = node[rson(x)].a1 = node[rson(x)].d = 0;
		node[x].setc = 0;
	}
	node[lson(x)].a1 += node[x].a1; 
	node[lson(x)].d += node[x].d;
	ll l = node[x].l, r = node[x].r;
	ll mid = (l + r) / 2;
	ll amid = node[x].a1 + node[x].d * (mid - l + 1);
	ll len1 = (mid - l + 1), len2 = (r - mid);
	node[lson(x)].val += node[x].a1 * len1 + len1 * (len1 - 1) / 2 * node[x].d;
	node[rson(x)].a1 += amid;
	node[rson(x)].d += node[x].d;
	node[rson(x)].val += amid * len2 + len2 * (len2 - 1) / 2 * node[x].d;
	node[x].a1 = node[x].d = 0;
}

void A(ll l, ll r, ll d, int x = 0) {
	if (node[x].l >= l && node[x].r <= r) {
		ll st = node[x].l - l + 1;
		if (d == -1) st = r - node[x].l + 1;
		node[x].a1 += st;
		node[x].d += d;
		ll len = node[x].r - node[x].l + 1;
		node[x].val += st * len + len * (len - 1) / 2 * d;
		return;
	} 
	pushdown(x);
	ll mid = (node[x].l + node[x].r) / 2;
	if (l <= mid) A(l, r, d, lson(x));
	if (r > mid) A(l, r, d, rson(x));
	pushup(x);
}

void C(ll l, ll r, ll c, int x = 0) {
	if (node[x].l >= l && node[x].r <= r) {
		node[x].setc = 1;
		node[x].c = c;
		node[x].val = (node[x].r - node[x].l + 1) * c;
		node[x].a1 = node[x].d = 0;
		return;
	}
	pushdown(x);
	ll mid = (node[x].l + node[x].r) / 2;
	if (l <= mid) C(l, r, c, lson(x));
	if (r > mid) C(l, r, c, rson(x));
	pushup(x);
}

ll S(ll l, ll r, int x = 0) {
	if (node[x].l >= l && node[x].r <= r)
		return node[x].val;
	pushdown(x);
	ll mid = (node[x].l + node[x].r) / 2;
	ll ans = 0;
	if (l <= mid) ans += S(l, r, lson(x));
	if (r > mid) ans += S(l, r, rson(x));
	pushup(x);
	return ans;
}

int main() {
	while (~scanf("%d", &n)) {
		build(1, 250000);
		ll a, b, c;
		char Q[2];
		while (n--) {
			scanf("%s%lld%lld", Q, &a, &b);
			if (Q[0] == 'C') scanf("%lld", &c);
			if (Q[0] == 'A') A(a, b, 1);
			if (Q[0] == 'B') A(a, b, -1);
			if (Q[0] == 'C') C(a, b, c);
			if (Q[0] == 'S') printf("%lld\n", S(a, b));
		}
	}
	return 0;
}







本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5414069.html,如需转载请自行联系原作者  

相关文章
|
3月前
|
算法 C++
POJ 3740 Easy Finding题解
这篇文章提供了一个使用舞蹈链(Dancing Links)算法解决POJ 3740 "Easy Finding" 问题的C++代码实现,该问题要求找出矩阵中能够使每一列都恰好包含一个1的行集合。
|
6月前
|
机器学习/深度学习 Java
hdu-2680-Choose the best route(dijkstra)
hdu-2680-Choose the best route(dijkstra)
29 0
light oj 1159 - Batman LCS
学过简单动态规划的人应该对最长公共子序列的问题很熟悉了,这道题只不过多加了一条字符串变成三条了,还记得,只要把状态变成三维的即可。
34 0
|
机器学习/深度学习
light oj 1005 - Rooks(组合数学)
组合数学解法 现在n行中选出m行,C(n,m),再在n列中选出m列随便放A(n,m),答案为C(n,m)*A(n,m)。
38 0
|
算法
light oj 1047 - Neighbor House 动态规划
动态规划,这个和刘汝佳算法竞赛入门经典P158的数字三角形有些相似,不过是求最小的值,而且有些限制,每次走到点和上次走的点不在同一列。
30 0
|
机器学习/深度学习
HDU-2680,Choose the best route(Dijkstra)
HDU-2680,Choose the best route(Dijkstra)
HDOJ(HDU) 2162 Add ‘em(求和)
HDOJ(HDU) 2162 Add ‘em(求和)
73 0
|
算法 机器学习/深度学习 消息中间件