hdu 3074 Multiply game

Problem Description

Tired of playing computer games, alpc23 is planning to play a game on numbers. Because plus and subtraction is too easy for this gay, he wants to do some multiplication in a number sequence. After playing it a few times, he has found it is also too boring. So he plan to do a more challenge job: he wants to change several numbers in this sequence and also work out the multiplication of all the number in a subsequence of the whole sequence.
  To be a friend of this gay, you have been invented by him to play this interesting game with him. Of course, you need to work out the answers faster than him to get a free lunch, He he…

Input

The first line is the number of case T (T<=10).
  For each test case, the first line is the length of sequence n (n<=50000), the second line has n numbers, they are the initial n numbers of the sequence a1,a2, …,an, 
Then the third line is the number of operation q (q<=50000), from the fourth line to the q+3 line are the description of the q operations. They are the one of the two forms:
0 k1 k2; you need to work out the multiplication of the subsequence from k1 to k2, inclusive. (1<=k1<=k2<=n) 
1 k p; the kth number of the sequence has been change to p. (1<=k<=n)
You can assume that all the numbers before and after the replacement are no larger than 1 million.

Output

For each of the first operation, you need to output the answer of multiplication in each line, because the answer can be very large, so can only output the answer after mod 1000000007.

Sample Input

1
6
1 2 4 5 6 3
3
0 2 5
1 3 7
0 2 5

Sample Output

240

420

這個題,一道線段樹的題,題目的意思容易理解。就是

先輸入一個序列,然後 後面m個數據。 第一個爲0的話,就

輸出第k1 到k2的之間的積,如果是0的話,就把第k 的值改成p

注意積的值對100000007取模, long long 下 lld輸出即可

無語的wa點在定義樹的結構體的時候,沒把節點的值long long

找錯 那個心累

#include<iostream>
#include<cstring>
using namespace std;
const int mod=1000000007;
struct node
{
	int left,right;
	long long num;
}s[150005];
int a[50010];

void build(int ll,int rr,int i) //建線段樹 
{
	int mm;
	s[i].left=ll;  s[i].right=rr;   //左右區間給樹的數組 
	if(ll==rr)   //達到葉結點 
	{
		s[i].num=a[ll]; //先用數組存下該隊的人
		return ;
	}
	mm=(ll+rr)/2;  //二分思想
	build(ll,mm,2*i);  //左子樹
	build(mm+1,rr,2*i+1); //右子樹
	s[i].num=(s[2*i].num*s[2*i+1].num)%mod;
}


void updata(int y,int x,int i) //值   位置  
{
	if(s[i].left==x&&x==s[i].right) 
	{
		s[i].num=y;
		return; //到達葉子節點
	} 
	if(x<=s[2*i].right)  updata(y,x,2*i);
	if(x>=s[2*i+1].left) updata(y,x,2*i+1);
	s[i].num=(s[2*i].num*s[2*i+1].num)%mod;
}


long long sum(int ll,int rr,int i) //查詢 
{
	int mm;
	if(s[i].left==ll&&rr==s[i].right) //如果區間覆蓋,則直接返回其節點的值 
	{
		return s[i].num;
	}
	mm=(s[i].left+s[i].right)/2;
	if(rr<=mm)  return sum(ll,rr,2*i); //左子樹 
	if(ll>mm) return sum(ll,rr,2*i+1); //右子樹 
	else 
	{
		long long a=sum(ll,mm,2*i);
		long long b=sum(mm+1,rr,2*i+1);
		return (a*b)%mod; //左右之間 
	}
}


int main()
{
	int bbs,k,i,j,n,m,x,y;
	scanf("%d",&bbs);
	while(bbs--)
	{
		scanf("%d",&n);
		for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
		build(1,n,1); //建樹
		scanf("%d",&m);
		while(m--)
		{
			scanf("%d%d%d",&k,&x,&y);
			if(k==0)
			{
				long long ans=sum(x,y,1);
				ans=ans%mod;
				printf("%lld\n",ans);
			}
			else updata(y,x,1);  //值 和 位置  
		} 
	}	
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章