2018ACM上海邀请赛A Simple Problem with Integers(找规律区间取模)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leekerian/article/details/89159412

题意

对于一个序列,进行以下两种操作:

1、C L R 修改区间[L,R]上每个值为本身的平方,取mod 2018 
2、Q L R 查询区间[L,R]的数值和

通过打表发现所有的数在前几项之后会进入循环部分,最大循环节为6,又所有未进入循环的部分<5所以我们对区间的维护是这样 的,定义sum[][]为这个节点的后6个数字,因为循环节是6所以我只要记录6个数字就可以,p[]为这个节点在循环节中的位置,cont[]为这个节点的操作次数,通过cont判断操作了几次如果>=5次说明这个节点进入循环部分不需要再更新到叶子节点了。

#include <iostream>
#include <algorithm>

using namespace std;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int MAXN=50050;

int sum[MAXN<<2][6],lazy[MAXN<<2],pos[MAXN<<2],cont[MAXN<<2];

void pushup(int rt)
{
	cont[rt]=min(cont[rt<<1],cont[rt<<1|1]);
    pos[rt]=0;
    if(cont[rt]>=5)
    {
        for(int i=0;i<6;i++)
            sum[rt][i]=sum[rt<<1][(pos[rt<<1]+i)%6]+sum[rt<<1|1][(pos[rt<<1|1]+i)%6];
    }
    else sum[rt][0]=sum[rt<<1][pos[rt<<1]]+sum[rt<<1|1][pos[rt<<1|1]];
}

void build(int l,int r,int rt)
{
	lazy[rt]=0,pos[rt]=0,cont[rt]=0;
	if(l==r)
	{
		int k;
		scanf("%d",&k);
		sum[rt][0]=k;
		return;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	pushup(rt);
}


void pushdown(int rt)
{
	if(lazy[rt])
	{
		lazy[rt<<1]+=lazy[rt];
		lazy[rt<<1|1]+=lazy[rt];
        pos[rt<<1]=(pos[rt<<1]+lazy[rt])%6;
        pos[rt<<1|1]=(pos[rt<<1|1]+lazy[rt])%6;
		lazy[rt]=0;
	}
}
void update(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R&&cont[rt]>=5)
	{
		lazy[rt]++;
        pos[rt]=(pos[rt]+1)%6;
		return;
	}
    if(l==r)
    {
        cont[rt]++;
        if(cont[rt]<5)
            sum[rt][0]=(sum[rt][0]*sum[rt][0])%2018;
        else if(cont[rt]==5)
        {
            sum[rt][0]=(sum[rt][0]*sum[rt][0])%2018;
            for(int i=1;i<6;i++)
                sum[rt][i]=(sum[rt][i-1]*sum[rt][i-1])%2018;
        }
        else 
            pos[rt]=(pos[rt]+1)%6;
        return;
    }
	pushdown(rt);
	int mid=(l+r)>>1;
	if(L<=mid) update(L,R,lson);
	if(R>mid) update(L,R,rson);
    pushup(rt);
}

int query(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R)
	{
		return sum[rt][pos[rt]];
	}
	int mid=(l+r)>>1;
	int ans=0;
	pushdown(rt);
	if(L<=mid) ans+=query(L,R,lson);
	if(R>mid) ans+=query(L,R,rson);
	return ans;
}
int main()
{
	int t;
	cin>>t;
	int kace=1;
	while(t--)
	{
		int n;
		printf("Case #%d:\n",kace++);
		scanf("%d",&n);
		build(1,n,1);
		int m;
		scanf("%d",&m);
		for(int i=0;i<m;i++)
		{
			char s[3];
			int x,y;
			scanf("%s%d%d",s,&x,&y);
			if(s[0]=='Q')
			{
				int ans=query(x,y,1,n,1);
				printf("%d\n",ans);
			}
			else if(s[0]=='C')
			{
				update(x,y,1,n,1);
			}
		}
	}	 
}

猜你喜欢

转载自blog.csdn.net/leekerian/article/details/89159412