UVa 12532 - Interval Product

本文介绍了一种使用线段树解决区间乘积符号查询及数值更新问题的方法。通过构造线段树并定义节点属性,实现了对区间内元素乘积符号的有效查询与修改。适用于需要快速查询区间乘积符号及更新特定位置数值的问题。

題目:已知N各數字X1~Xn,執行兩種操作:1、改變Xi為A;2、求區間[L,R]上元素乘積的符號。

分析:DS,線段樹。利用線段樹處理即可,每個數字正的取1,負的取-1,否則取0。

說明:╮(╯▽╰)╭。

#include <cstdlib>
#include <cstring>
#include <cstdio>

int data[100001];

//segment_tree__begin
typedef struct tnode
{
	tnode* Lchild;
	tnode* Rchild;
	int    Lvalue;
	int    Rvalue;
	int    Value;
}tnode;

tnode  Node[200002];
tnode* Root;
int    Count;

tnode* buildtree(int a, int b) 
{
	tnode* np = &Node[Count ++];
	np->Lvalue = a;
	np->Rvalue = b;
	np->Value = 0;
	if (a < b) {
		np->Lchild = buildtree(a, (a+b)/2);
		np->Rchild = buildtree((a+b)/2+1, b);
	}else {
		np->Lchild = NULL;
		np->Rchild = NULL;
	}
	return np;
} 

void segment_tree(int a, int b)
{
	Count = 0;
	Root = buildtree(a, b);
}

void Insert(tnode*r, int a, int b, int v) 
{
	if (r->Lvalue == a && r->Rvalue == b) {
		r->Value = v;
		return;
	}
	if (b <= r->Lchild->Rvalue) {
		Insert(r->Lchild, a, b, v);
	}else if (a >= r->Rchild->Lvalue) {
		Insert(r->Rchild, a, b, v);
	}
	r->Value = r->Lchild->Value * r->Rchild->Value;
}

int Query(tnode* r, int a, int b) 
{
	if (r->Lvalue == a && r->Rvalue == b) {
		return r->Value;
	}else if (b <= r->Lchild->Rvalue) {
		return Query(r->Lchild, a, b);
	}else if (a >= r->Rchild->Lvalue) {
		return Query(r->Rchild, a, b);
	}else {
		return Query(r->Lchild, a, r->Lchild->Rvalue) * Query(r->Rchild, r->Rchild->Lvalue, b);
	}
}

void Insert(int a, int b, int v) 
{
	Insert(Root, a, b ,v);
}

int Query(int a, int b) 
{
	return Query(Root, a, b);
}
//segment_tree__end 

int main()
{
	int  N, K, value1, value2, ans;
	char operators[2];
	while (~scanf("%d%d",&N,&K)) {
		for (int i = 1; i <= N; ++ i) {
			scanf("%d",&data[i]);
		}
		segment_tree(1, N);
		for (int i = 1; i <= N; ++ i) {
			if (data[i] > 0) {
				Insert(i, i, 1);
			}else if (data[i] < 0) {
				Insert(i, i, -1);
			}else {
				Insert(i, i, 0);
			}
		}
		for (int i = 1; i <= K; ++ i) {
			scanf("%s%d%d",operators,&value1,&value2);
			if (operators[0] == 'C') {
				if (value2 > 0) {
					Insert(value1, value1, 1);
				}else if (value2 < 0) {
					Insert(value1, value1, -1);
				}else {
					Insert(value1, value1, 0);
				}
			}else {
				ans = Query(value1, value2);
				if (ans > 0) {
					printf("+");
				}else if (ans < 0) {
					printf("-");
				}else {
					printf("0");
				}
			}
		}
		puts("");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值