HDU - 5475 An easy problem 线段树

题意:
每次给定两种操作中的一种
操作1:乘上x 然后%mod 输出
操作2:除以第x次操作乘的那个数,输出mod

思路:
由于模的存在,不能直接除以之前乘的那个数,暴力能水过,我们考虑线段树
线段树记录区间乘积
对于每个点i(对应于第i次操作),如果是乘法,就把该点更新成x,如果是除法,就更新成1,这样就相当于没成。然后查询区间乘积,区间是1~当前的i,其实也可以直接输出根节点的值,因为后面没涉及到的在建树时初始化成了1.

#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e5+5;
int mod;
struct node{
	int l,r;
	ll val;
}tree[maxn<<2];
void pushup(int m)
{
	tree[m].val=tree[m<<1].val*tree[m<<1|1].val%mod;
}
/*void pushdown(int m)
{
	if(tree[m].lazy)
	{
		tree[m<<1].lazy+=tree[m].lazy;
		tree[m<<1|1].lazy+=tree[m].lazy;
		tree[m<<1].val+=(tree[m<<1].r-tree[m<<1].l+1)*tree[m].lazy;
		tree[m<<1|1].val+=(tree[m<<1|1].r-tree[m<<1|1].l+1)*tree[m].lazy;
		tree[m].lazy=0;
	}
}*/
void build(int m,int l,int r)
{
	tree[m].l=l;
	tree[m].r=r;
	if(l==r)
	{
		tree[m].val=1;
		return ;
	}
	int mid=(l+r)>>1;
	build(m<<1,l,mid);
	build(m<<1|1,mid+1,r);
	pushup(m);
}
void update(int m,int index,int val)
{
	if(tree[m].l==index&&tree[m].r==index)
	{
		tree[m].val=val;
		return;
	}
	int mid=(tree[m].l+tree[m].r)>>1;
	if(index<=mid)
		update(m<<1,index,val);
	else 
		update(m<<1|1,index,val);
	pushup(m);
}
/*void query(int m,int l,int r)
{
	if(tree2[m].l==l&&tree2[m].r==r)
	{
		minn=min(tree2[m].val,minn);
		return;
	}
	int mid=(tree2[m].l+tree2[m].r)>>1;
	if(r<=mid)
		querymin(m<<1,l,r);
	else if(l>mid)
		querymin(m<<1|1,l,r);
	else
		querymin(m<<1,l,mid),querymin(m<<1|1,mid+1,r);
}*/
int main()
{
	int n,q,t,ok=1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&q,&mod);
		build(1,1,q);
		printf("Case #%d:\n",ok++);
		for(int i=1;i<=q;i++)
		{
			int op;
			ll x;
			scanf("%d%lld",&op,&x);
			if(op==1)
				update(1,i,x);
			else
				update(1,x,1);
			printf("%lld\n",tree[1].val);
		}
	}
	return 0;	
} 

你可能感兴趣的:(线段树树状数组)