hdu 5475(线段树)

题意:

两个操作:① 当为1时 ,乘上后面的数

                  ② 当为2时,除以第x次乘的数

还说了2操作后面的n不会重复(就这明显看出线段树- -,然而并没有看出来,还是靠的队友)

1则对每个节点赋值,2则将相应的点改为一,每次操作后进行一次询问


#include <cstdio>
#define MAXN 100010
using namespace std;

long long m,ans[MAXN],q[MAXN],tree[MAXN*50];
int n;
long long build(int l,int r,int rt)
{
    if(l==r) return(tree[rt]=q[l]>1?q[l]:1);
    int mid=(l+r)/2;
    return tree[rt]=(build(l,mid,rt*2)*build(mid+1,r,rt*2+1))%m;
}
long long change(int l,int r,int rt,int x)
{
    if(l==r)return tree[rt]=1;
    int mid=(l+r)/2;
    if(x<=mid)return tree[rt]=(change(l,mid,rt*2,x)*tree[rt*2+1])%m;
    else return tree[rt]=(tree[rt*2]*change(mid+1,r,rt*2+1,x))%m;
}
long long query(int l,int r,int rt,int x)
{
    if(r==x)return tree[rt];
    int mid=(l+r)/2;
    if(x>mid)return (tree[rt*2]*query(mid+1,r,rt*2+1,x))%m;
    else return query(l,mid,rt*2,x);
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int t=1; t<=T; ++t)
    {
        scanf("%d%lld",&n,&m);
        int op;
        ans[0]=1;
        for(int i=1; i<=n; i++)
        {
            ans[i]=1;
            scanf("%d%lld",&op,&q[i]);
            q[i]%=m;if(op==2)q[i]=-q[i];
        }
        build(1,n,1);
        printf("Case #%d:\n",t);
        for(int i=1; i<=n; i++)
        {
            if(q[i]>=0)ans[i]=(ans[i-1]*q[i])%m;
            else
            {
                change(1,n,1,-q[i]);
                ans[i]=query(1,n,1,i);
            }
            printf("%lld\n",ans[i]);
        }
    }
    return 0;
}

  

posted @ 2015-09-27 23:27  Przz  阅读(125)  评论(0编辑  收藏  举报