UVA 12532 - Interval Product(线段树单点更新&区间乘积正负)

It’s normal to feel worried and tense the day before a programming contest. To relax, you went out for a drink with some friends in a nearby pub. To keep your mind sharp for the next day, you decided to
play the following game. To start, your friends will give you a sequence of N integers X1, X2, . . . , XN.
Then, there will be K rounds; at each round, your friends will issue a command, which can be:
• a change command, when your friends want to change one of the values in the sequence; or
• a product command, when your friends give you two values I, J and ask you if the product XI × XI+1 × . . . × XJ−1 × XJ is positive, negative or zero.
Since you are at a pub, it was decided that the penalty for a wrong answer is to drink a pint of beer. You are worried this could affect you negatively at the next day’s contest, and you don’t want
to check if Ballmer’s peak theory is correct. Fortunately, your friends gave you the right to use your
notebook. Since you trust more your coding skills than your math, you decided to write a program to
help you in the game.

Input

Each test case is described using several lines. The first line contains two integers N and K, indicating
respectively the number of elements in the sequence and the number of rounds of the game (1 ≤N, K ≤ 105). The second line contains N integers Xi that represent the initial values of the sequence
(−100 ≤ Xi ≤ 100 for i = 1, 2, . . . , N). Each of the next K lines describes a command and starts with an uppercase letter that is either ‘C’ or ‘P’. If the letter is ‘C’, the line describes a change command, and
the letter is followed by two integers I and V indicating that XI must receive the value V (1 ≤ I ≤ N and −100 ≤ V ≤ 100). If the letter is ‘P’, the line describes a product command, and the letter
is followed by two integers I and J indicating that the product from XI to XJ , inclusive must be calculated (1 ≤ I ≤ J ≤ N). Within each test case there is at least one product command.

Output

For each test case output a line with a string representing the result of all the product commands in
the test case. The i-th character of the string represents the result of the i-th product command. If the
result of the command is positive the character must be ‘+’ (plus); if the result is negative the character
must be ‘-’ (minus); if the result is zero the character must be ‘0’ (zero).

Sample Input

4 6
-2 6 0 -1
C 1 10
P 1 4
C 3 7
P 2 2
C 4 -5
P 1 4
5 9
1 5 -2 4 3
P 1 2
P 1 5
C 4 -5
P 1 5
P 4 5
C 3 0
P 1 5
C 4 -5
C 4 -5

Sample Output


±±0

在进行编程比赛的前一天感到紧张和紧张是很正常的。为了放松,您和附近的一些酒吧的朋友出去喝了一杯酒。为了第二天保持敏锐的头脑,您决定
玩以下游戏。首先,您的朋友会给您N个整数X1,X2,…的序列。 。 。 ,XN。
然后,将有K轮;在每一轮中,您的朋友都会发出一条命令,该命令可以是:
•更改命令,当您的朋友想要更改序列中的值之一时;要么
•产品命令,当您的朋友给您两个值I,J并询问您产品是否
XI×XI + 1×。 。 。 ×XJ-1×XJ为正,负或零。
由于您在酒吧里,因此决定错误答案的惩罚是喝一品脱的
啤酒。您担心这会在第二天的比赛中对您造成负面影响,并且您不想
检查鲍尔默的峰值理论是否正确。幸运的是,您的朋友给了您使用您的权利
笔记本。由于您相信自己的编码技能胜过数学,因此您决定编写一个程序来
在游戏中帮助您。
输入
每个测试用例用几行描述。第一行包含两个整数N和K,表示
序列中的元素数和游戏的回合数(1≤N,K≤105)。第二行包含N个整数Xi,它们代表序列的初始值
(对于i = 1、2,…,N,−100≤Xi≤100)。接下来的K行每行都描述一个命令,并以大写字母“ C”或“ P”开头。如果字母为“ C”,则该行描述更改命令,并且字母后跟两个整数I和V,指示XI必须接收值V(1≤I≤N和-100≤V≤100)。如果字母是“ P”,则该行描述产品命令,并且字母
后跟两个整数I和J,表示必须计算从XI到XJ的乘积(包括1≤I≤J≤N)。在每个测试用例中,至少有一个产品命令。
输出
对于每个测试用例,输出一行带有字符串的行,该字符串表示以下所有产品命令的结果
测试用例。字符串的第i个字符表示第i个乘积命令的结果。如果
命令的结果为正,字符必须为“ +”(加号);如果结果为负,则字符
必须为“-”(减号);如果结果为零,则字符必须为“ 0”(零)。
输入
4 6
-2 6 0 -1
C 1 10
P 1 4
C 3 7
P 2 2
C 4 -5
P 1 4
5 9
1 5 -2 4 3
P 1 2
P 1 5
C 4 -5
P 1 5
P 4 5
C 3 0
P 1 5
C 4 -5
C 4 -5
输出

±±0

题目大意:
多组输入,每组输入n和k,表示有n个数和k个操作,然后输入n个数,再输入k个命令,如果是C,则把a[i]的值改成v,如果是P,则判断a[l]x…xa[v]的值的符号,并将其输出。

解题思路:
这是线段树的一道很基础的题,不过要注意的是,我们可以在建树的时候把大于0的数全部变成1,把小于0的数全变成-1,0就是0,就可以防止溢出了。在update的时候也这样做就可以,乘积正常做。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int _max=1e5+50;
int a[_max],tree[4*_max];
void bd(int node,int start,int end)
{
	if(start==end)//这里判断一下
	{
		if(a[start]>0)
		  tree[node]=1;
		else if(a[start]<0)
		  tree[node]=-1;
		else
		  tree[node]=0;
		return;
	}
	int mid=(start+end)>>1;
	bd(node*2,start,mid);
	bd(node*2+1,mid+1,end);
	tree[node]=tree[node*2]*tree[node*2+1];
	return;
}
void update(int node,int start,int end,int idx,int val)
{
	if(start==end)
	{
		a[idx]=val;
		tree[node]=val;
		return;
	}
	int mid=(start+end)>>1;
	if(idx<=mid)
	  update(node*2,start,mid,idx,val);
	else
	  update(node*2+1,mid+1,end,idx,val);
	tree[node]=tree[node*2]*tree[node*2+1];  
}
int query(int node,int start,int end,int l,int r)
{
	if(l<=start&&r>=end)
	  return tree[node];
	int mid=(start+end)>>1;
	int ans=1;
	if(l<=mid)
	  ans*=query(node*2,start,mid,l,r);
	if(r>mid)
	  ans*=query(node*2+1,mid+1,end,l,r);
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	int n,k;
	while(cin>>n>>k)
	{
		for(int i=1;i<=n;i++)
		  cin>>a[i];
		bd(1,1,n);
		string str;
		while(k--)
		{
			string c;
			int l,r;
			cin>>c>>l>>r;
			//cout<<c<<" "<<l<<" "<<r<<" "<<"T"<<endl;
			if(c=="C")//这里也做一下判断
			{
				if(r>0)
				  update(1,1,n,l,1);
				else if(r<0)
				  update(1,1,n,l,-1);
				else
				  update(1,1,n,l,0);  
			}
			else
			{
				int ans=query(1,1,n,l,r);
				if(ans>0)
				  str+="+";
				else if(ans<0)
				  str+="-";
				else
				  str+='0';   
			}
		}
		cout<<str<<endl;
	}
	//system("pause");
	return 0;
}
posted @ 2020-04-04 18:46  Hayasaka  阅读(72)  评论(0编辑  收藏  举报