HDU 5475 线段树 + 乘法+取模

来源:互联网 发布:淘宝网tfboys同款书包 编辑:程序博客网 时间:2024/06/04 01:38

线段树 + 乘法+取模

题意:

​ 有一个数字最开始是1,现在有两种操作,1. 乘以一个数字y,取模输出答案2. 除以一个之前乘以的数字,取模输出答案。

思路:

​ 操作次数有1e5个,直接乘法也有可能,但是问题是一些数字乘了又除了,直接写很容易由于精度的问题爆了。而线段树竟然可以这样解决!!!线段树维护所有操作,核心操作是乘法,当除以一个数字时,就把那个数字改为1,然后轻轻松松根据回溯就可以不超精度解决,并且让x没必要一直保持一个很大的状态,线段树每次重新利用到没有修改的结果进行修改即可。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long LL;const int maxn = 1e5;struct Tree{    int l,r;    LL mul;}rt[maxn*4];int n;int mod;void build(int root,int l,int r){    rt[root].l = l,rt[root].r = r;    rt[root].mul = 1;    if(l == r) return ;    int mid = (l+r)>>1;    build(root<<1,l,mid);    build(root<<1|1,mid+1,r);    return ;}void push_up(int root){    rt[root].mul = (rt[root<<1].mul*rt[root<<1|1].mul)%mod;}void update(int root,int l,int r,int c){    if(rt[root].l > r || rt[root].r < l) return ;    if(rt[root].l >= l && rt[root].r <= r) {        rt[root].mul = c;        return ;    }    update(root<<1,l,r,c);    update(root<<1|1,l,r,c);    push_up(root);}int main(){    //freopen("in.txt","r",stdin);    int t,ncase = 1;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&mod);        build(1,1,n);        printf("Case #%d:\n",ncase++);        for(int i = 1;i <= n; i++) {            int op ;            scanf("%d",&op);            if(op == 1) {                int y;                scanf("%d",&y);                update(1,i,i,y);                printf("%I64d\n",rt[1].mul);            }            else {                int ith;                scanf("%d",&ith);                update(1,ith,ith,1);                printf("%I64d\n",rt[1].mul);            }        }    }    return 0;}
原创粉丝点击