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));
}
}