您的位置:首页 > 其它

hdu 5475(线段树)

2015-09-27 23:27 260 查看
题意:

两个操作:① 当为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;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: