hdu5475(线段树单点修改,统计区间乘积)
题目意思:
给定a*b*c*d*e*f*....,可以在某一步去掉前面的一个因子,每次回答乘积。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #define LL long long using namespace std; LL Q,MOD; //线段树 //区间每点增值,求区间和 const int maxN = 110000; struct node { int lt, rt; LL val; }tree[4*maxN]; //向上更新 void pushUp(int id) { tree[id].val = (tree[id<<1].val * tree[id<<1|1].val)%MOD; } //建立线段树 void build(int lt, int rt, int id) { tree[id].lt = lt; tree[id].rt = rt; tree[id].val = 1;//每段的初值,根据题目要求 if (lt == rt) { tree[id].val=1; return; } int mid = (lt+rt)>>1; build(lt, mid, id<<1); build(mid+1, rt, id<<1|1); pushUp(id); } //增加区间内每个点固定的值 void add(int lt, int rt, int id, int pls) { if (lt <= tree[id].lt && rt >= tree[id].rt) { if(pls!=-1) { tree[id].val *= pls; tree[id].val %= MOD; } if(pls==-1) tree[id].val =1; return; } int mid = (tree[id].lt+tree[id].rt)>>1; if (lt <= mid) add(lt, rt, id<<1, pls); if (rt > mid) add(lt, rt, id<<1|1, pls); pushUp(id); } //查询某段区间内的和 LL query(int lt, int rt, int id) { if (lt <= tree[id].lt && rt >= tree[id].rt) return tree[id].val; int mid = (tree[id].lt+tree[id].rt)>>1; LL ans = 1; if (lt <= mid) ans = (ans * query(lt, rt, id<<1) ) %MOD; if (rt > mid) ans = (ans * query(lt, rt, id<<1|1) ) %MOD; return ans; } int main() { //freopen("test.txt","r",stdin); int t; scanf("%d",&t); int Case=0; while(t--) { scanf("%I64d%I64d",&Q,&MOD); build(1,Q,1); printf("Case #%d:\n",++Case); for(int i=1;i<=Q;i++) { LL x,m; scanf("%I64d%I64d",&x,&m); if(x==1) add(i,i,1,m); else if(x==2) add(m,m,1,-1); printf("%I64d\n",tree[1].val); } } return 0; }