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