线段树(单点修改+an easy problem)(在线)-----太聪明了

题目链接

One day, a useless calculator was being built by Kuros. Let's assume that number X is showed on the screen of calculator. At first, X = 1. This calculator only supports two types of operation. 
1. multiply X with a number. 
2. divide X with a number which was multiplied before. 
After each operation, please output the number X modulo M. 

Input

The first line is an integer T(1≤T≤101≤T≤10), indicating the number of test cases. 
For each test case, the first line are two integers Q and M. Q is the number of operations and M is described above. (1≤Q≤105,1≤M≤1091≤Q≤105,1≤M≤109) 
The next Q lines, each line starts with an integer x indicating the type of operation. 
if x is 1, an integer y is given, indicating the number to multiply. (0<y≤1090<y≤109) 
if x is 2, an integer n is given. The calculator will divide the number which is multiplied in the nth operation. (the nth operation must be a type 1 operation.) 

It's guaranteed that in type 2 operation, there won't be two same n. 

Output

For each test case, the first line, please output "Case #x:" and x is the id of the test cases starting from 1. 
Then Q lines follow, each line please output an answer showed by the calculator. 

Sample Input

1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7

Sample Output

Case #1:
2
1
2
20
10
1
6
42
504
84
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
struct node{
	ll l,r,sum;
}a[400000];
ll n,m;
void build(ll k,ll l,ll r){
	a[k].l=l;
	a[k].r=r;
	if(l==r){
		a[k].sum=1;//一开始所有叶节点都是1,因为线段树进行的乘操作 
		return ;
	}
	ll mid=(a[k].l+a[k].r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	a[k].sum=((a[k<<1].sum%m)*(a[k<<1|1].sum%m))%m;//update函数 
	return ;
}
void change(ll k,ll pos,ll y){
	if(a[k].l==a[k].r){
		a[k].sum=y;//把指定位置的叶节点改为y 
		return ;
	}
	ll mid=(a[k].l+a[k].r)>>1;
	if(pos<=mid){
		change(k<<1,pos,y);
	}
	else change(k<<1|1,pos,y);
	a[k].sum=((a[k<<1].sum%m)*(a[k<<1|1].sum%m))%m;
	return ;
}
ll query(ll k,ll l,ll r){
	if(a[k].l>=l&&a[k].r<=r){
		return a[k].sum;
	}
	ll mid=(a[k].l+a[k].r)>>1;
	ll res=1;
	//求[l,r]的区间的元素的乘积 
	if(l<=mid){
		res=(res*query(k<<1,l,r))%m;
	}
	if(r>mid){
		res=(res*query(k<<1|1,l,r))%m;
	}
	return res;
}

int main(){
	ll t,cnt=1;
	scanf("%lld",&t);
//	getchar();
	while(t--){
		printf("Case #%lld:\n",cnt++);
		scanf("%lld %lld",&n,&m);
	//	getchar();
		build(1,1,n);
		for(ll i=1;i<=n;i++){
			ll sign,y;
			scanf("%lld %lld",&sign,&y);
		//	getchar();
			if(sign==1){
				//如果要乘,把该叶节点改为要乘的那个数 
				change(1,i,y);
				printf("%lld\n",query(1,1,i));
			}
			else {
				//要把第y步输入的叶节点值除掉,就改为1 
				change(1,y,1);
				printf("%lld\n",query(1,1,i));
			}
		}
	}
	return 0;
}
/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */
// warm heart, wagging tail,and a smile just for you!
//
//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                           O\  =  /O
//                        ____/`---'\____
//                      .'  \|     |//  `.
//                     /  \|||  :  |||//  \
//                    /  _||||| -:- |||||-  \
//                    |   | \\  -  /// |   |
//                    | \_|  ''\---/''  |   |
//                    \  .-\__  `-`  ___/-. /
//                  ___`. .'  /--.--\  `. . __
//               ."" '<  `.___\_<|>_/___.'  >'"".
//              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//              \  \ `-.   \_ __\ /__ _/   .-` /  /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值