ZOJ4009
题意:
给出n个数字,有两种操作:
:将变成;
:求模99971的结果。
思路:
打表可以发现,在该模数下,每48个数字会有循环节。所以开48棵线段树,在v[0]里放当前值。
对于修改操作,进行左移就可以了。
不清楚的话可以自己模拟一下。
因为刚开始,所以一开始就要模99971。
这题有点卡常,虽然跑过了但是太慢了,用个读入挂比较好。
代码:
#define MOD 99971
typedef long long ll;
struct node
{
int left,right;
int f;
ll v[50];
}node[100010<<2];
ll temp1[50],temp2[50];
ll ans;
void pushup(int id)
{
for(int i=0;i<48;i++)
node[id].v[i]=(node[id<<1].v[i]+node[id<<1|1].v[i])%MOD;
}
void build(int l,int r,int id)
{
node[id].left=l;node[id].right=r;
node[id].f=0;
if(l==r)
{
scanf("%lld",&node[id].v[0]);
node[id].v[0]%=MOD;
for(int i=1;i<48;i++)
node[id].v[i]=node[id].v[i-1]*node[id].v[i-1]*node[id].v[i-1]%MOD;
return;
}
int m=(l+r)>>1;
build(l,m,id<<1);
build(m+1,r,id<<1|1);
pushup(id);
}
void pushdown(int id)
{
int c=node[id].f;
node[id<<1].f=(node[id<<1].f+c)%48;
node[id<<1|1].f=(node[id<<1|1].f+c)%48;
for(int i=0;i<48;i++)
{
temp1[i]=node[id<<1].v[i];
temp2[i]=node[id<<1|1].v[i];
}
for(int i=0;i<48;i++)
{
node[id<<1].v[i]=temp1[(i+c)%48];
node[id<<1|1].v[i]=temp2[(i+c)%48];
}
node[id].f=0;
}
void update(int L,int R,int id)
{
int l=node[id].left,r=node[id].right;
if(l>=L&&r<=R)
{
node[id].f=(node[id].f+1)%48;
for(int i=0;i<48;i++)
temp1[i]=node[id].v[i];
for(int i=0;i<48;i++)
node[id].v[i]=temp1[(i+1)%48];
return;
}
if(node[id].f)pushdown(id);
int m=(l+r)>>1;
if(L<=m)update(L,R,id<<1);
if(R>m)update(L,R,id<<1|1);
pushup(id);
}
void query(int L,int R,int id)
{
int l=node[id].left,r=node[id].right;
if(l>=L&&r<=R)
{
ans=(ans+node[id].v[0])%MOD;
return;
}
if(node[id].f)pushdown(id);
int m=(l+r)>>1;
if(L<=m)query(L,R,id<<1);
if(R>m)query(L,R,id<<1|1);
}
int main()
{
int t,n,q,op,x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--)
{
scanf("%d%d%d",&op,&x,&y);
if(op==1)
update(x,y,1);
else if(op==2)
{
ans=0;
query(x,y,1);
printf("%lld\n",ans);
}
}
}
return 0;
}
上海大都会赛H
题意:
给出n个数字,有两种操作:
:将变成;
:求的结果(不用取模)。
思路:
打表可知循环节大概是在变换4次以后,且每个循环节的长度为6。
所以这里就需要一个标记circle来记录该区间是否进入了循环节,如果进入了循环节,就像上题那样的做法,如果没有进入,则单点更新,并且判断更新后是否进入循环节。
上传标记的时候,只有左儿子和右儿子都在区间内的时候,将6个v[i]更新,否则就只更新v[0]。
我query的时候标记没有下放…debug了好久…一写长的代码就要debug好久…
代码:
typedef long long ll;
struct node
{
int left,right;
bool cir;
int f;
int v[10];
}node[50010<<2];
int temp1[10],temp2[10];
ll ans;
bool judge(int cur)
{
int x=cur;
for(int i=0;i<6;i++)
{
x=x*x%2018;
if(x==cur)return true;
}
return false;
}
void build(int l,int r,int id)
{
node[id].left=l;node[id].right=r;
node[id].cir=false;node[id].f=0;
if(l==r)
{
scanf("%d",&node[id].v[0]);
return;
}
int m=(l+r)>>1;
build(l,m,id<<1);
build(m+1,r,id<<1|1);
node[id].v[0]=(node[id<<1].v[0]+node[id<<1|1].v[0]);
}
void pushdown(int id)
{
int c=node[id].f;
node[id<<1].f=(node[id<<1].f+c)%6;
node[id<<1|1].f=(node[id<<1|1].f+c)%6;
for(int i=0;i<6;i++)
{
temp1[i]=node[id<<1].v[i];
temp2[i]=node[id<<1|1].v[i];
}
for(int i=0;i<6;i++)
{
node[id<<1].v[i]=temp1[(i+c)%6];
node[id<<1|1].v[i]=temp2[(i+c)%6];
}
node[id].f=0;
}
void update(int L,int R,int id)
{
int l=node[id].left,r=node[id].right;
if(l>=L&&r<=R&&node[id].cir)//循环内
{
node[id].f=(node[id].f+1)%6;
for(int i=0;i<6;i++)
temp1[i]=node[id].v[i];
for(int i=0;i<6;i++)
node[id].v[i]=temp1[(i+1)%6];
return;
}
if(l==r)//循环外
{
node[id].v[0]=node[id].v[0]*node[id].v[0]%2018;
if(judge(node[id].v[0]))
{
node[id].cir=true;
for(int i=1;i<6;i++)
node[id].v[i]=node[id].v[i-1]*node[id].v[i-1]%2018;
}
return;
}
if(node[id].f)pushdown(id);
int m=(l+r)>>1;
if(L<=m)update(L,R,id<<1);
if(R>m)update(L,R,id<<1|1);
if(node[id<<1].cir&&node[id<<1|1].cir)
{
node[id].cir=true;
for(int i=0;i<6;i++)
node[id].v[i]=node[id<<1].v[i]+node[id<<1|1].v[i];
}
else
{
node[id].cir=false;
node[id].v[0]=node[id<<1].v[0]+node[id<<1|1].v[0];
}
}
void query(int L,int R,int id)
{
int l=node[id].left,r=node[id].right;
if(l>=L&&r<=R)
{
ans+=1ll*node[id].v[0];
return;
}
if(node[id].f)pushdown(id);//不要忘了下放
int m=(l+r)>>1;
if(L<=m)query(L,R,id<<1);
if(R>m)query(L,R,id<<1|1);
}
int main()
{
int t,n,q,x,y;
char s[5];
scanf("%d",&t);
for(int kase=1;kase<=t;kase++)
{
printf("Case #%d:\n",kase);
scanf("%d",&n);
build(1,n,1);
scanf("%d",&q);
while(q--)
{
scanf("%s%d%d",s,&x,&y);
if(s[0]=='C')
update(x,y,1);
else if(s[0]=='Q')
{
ans=0;
query(x,y,1);
printf("%lld\n",ans);
}
}
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!