snoi多校模擬賽 1.18 t1 query

A 查詢(query.pas/c/cpp)

TL:5S  ML:512MB

【Description】

給定一個含有N個非負整數的序列,請寫一個程序,支持以下兩個操作:

1、Q l r  表示求l至r這一段所有數的和,結果對329701061取模

2、C l r   表示將l至r這一段中的每一個數變爲其立方。

【Input】

第一行一個整數N。

接下來N行,每行一個整數a[i],表示初始序列。

接下來一個整數Q,表示操作數量。

接下來Q行,每行一個操作,格式見上。

【Output】

對於每個Q操作,進行回答。

【Sample Input

3

8 3 4

5

Q 1 2

C 2 3

Q 1 3

C 1 2

Q 2 3              

【Sample Output

11

99

19747

【Hint】

 

20%:N, Q <= 1000

40%:N, Q<=30000

60%:N, Q <= 50000

另外20%:對於所有的C操作, l=r

100%:N, Q<=100000,初始數值在0…329701060內。

首先,這題打表找規律,發現每個數模329701061意義下48個週期一循環

所以線段樹中要保存48個值,足以解決本題。

之後就是裸的線段樹

代碼:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define rson ((now<<1)|1)
#define lson (now<<1)
#define mid ((s[now].l+s[now].r)>>1)
#define ll long long
#define ljm 329701061
#define zrx 48
struct nod
{
	ll v[50],l,r,z;
	nod(int l=0,int r=0,int z=0):l(l),r(r),z(z){memset(v,0,sizeof(v));}
}s[400005];
int a[100005],n,q,ql,qr;
ll li(ll a)
{
	return (((a*a)%ljm)*a)%ljm;
}
void update(int now)
{
	for(int i=0;i<48;i++) 
		s[now].v[i]=(s[lson].v[i]+s[rson].v[i])%ljm;
}
void add(int now,int V)
{
	ll tmp[50];
	for(int i=0;i<48;i++) tmp[i]=s[now].v[i];
	for(int i=0;i<48;i++) s[now].v[i]=tmp[(i+V)%zrx];
}
void down(int now)
{
	if(!s[now].z) return;
	add(lson,s[now].z);
	add(rson,s[now].z);
	s[lson].z=(s[lson].z+s[now].z)%zrx;
	s[rson].z=(s[rson].z+s[now].z)%zrx;
	s[now].z=0;
}
void build(int now,int L,int R)
{
	s[now]=nod(L,R,0);
	if(L==R)
	{
		s[now].v[0]=a[L];
		for(int i=1;i<48;i++)
			s[now].v[i]=li(s[now].v[i-1]);
		return;
	}
	build(now*2,L,mid);
	build(now*2+1,mid+1,R);
	update(now);
}
void Add(int now,int L,int R)
{
	if(s[now].l>=L&&s[now].r<=R)
	{
		s[now].z=(s[now].z+1)%zrx;
		add(now,1);
		return;
	}
	down(now);
	if(L<=mid) Add(now*2,L,R);
	if(R>mid) Add(now*2+1,L,R);
	update(now);
}
ll query(int now,int L,int R)
{
	if(s[now].l>=L&&s[now].r<=R) return s[now].v[0];
	down(now);
	ll ans=0;
	if(L<=mid) ans=(ans+query(now*2,L,R))%ljm;
	if(R>mid) ans=(ans+query(now*2+1,L,R))%ljm;
	return ans;
}
char c[1];
int main()
{
	freopen("query.in ","r",stdin);
	freopen("query.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
	build(1,1,n);
	scanf("%d",&q);
	while(q--)
	{
		scanf("%s%d%d",c,&ql,&qr);
		if(c[0]=='C') Add(1,ql,qr);
		else printf("%d\n",query(1,ql,qr));
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章