说在前面:“CDQZ”系列题目数据绝对良心(良苦用心233),提交网址如有需要请私信本蒟蒻。
1004:Challenge 4
查看 提交 统计 提问
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 262144kB
描述
给一个长为N的数列,有M次操作,每次操作时以下三种之一:
(1)修改数列中的一个数
(2)求数列中某连续一段所有数的两两乘积的和 mod 1000000007
(3)求数列中某连续一段所有相邻两数乘积的和 mod 1000000007
输入
第一行两个正整数N和M。
第二行N的整数表示这个数列。
接下来M行,每行开头是一个字符,若该字符为’M’,则表示一个修改操作,接下来两个整数x和y,表示把x位置的值修改为y;若该字符为’Q’,则表示一个询问操作,接下来两个整数x和y,表示对[x,y]区间做2号询问;若该字符为’A’,则表示一个询问操作,接下来两个整数x和y,表示对[x,y]区间做3号询问。
输出
对每一个询问操作单独输出一行,表示答案。
样例输入
5 5
1 2 3 4 5
Q 1 5
A 1 5
M 2 7
Q 1 5
A 1 5
样例输出
85
40
150
60
提示
1<=N<=10^5,1<=M<=10^5,输入保证合法,且所有整数可用带符号32位整型存储。
题解:线段树操作即可,在进行第一种询问(Q)时,由于同时需要区间的两个信息:1.区间和2.所有数两两乘积之和,所以可以写个pair,也可以单独写一个query_sum()函数询问区间和,前一个是O(nlog(n))的,后者目测应该是O(nlog(n)log(n))的,所以机智的本蒟蒻选择了写pair。
注意两点:1.凡是要乘爆int的,即使会取余,也要开longlong或者转longlong 2.有负数取余一定要再加一次再模一次。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<utility>
#define root 1,1,n
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
typedef long long ll;
const int MAXN=1e5+2;
const ll MOD=1e9+7;
int n,m;
ll sum[MAXN<<2],sa[MAXN<<2],sb[MAXN<<2],num[MAXN];
typedef pair<ll,ll> pa;
inline int read() {
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
inline void pushup(int rt,int mid) {
int l=rt<<1,r=rt<<1|1;
sum[rt]=(sum[l]+sum[r])%MOD;
sa[rt]=((sa[l]+sa[r])%MOD+sum[l]*sum[r]%MOD)%MOD;
sb[rt]=((sb[l]+sb[r])%MOD+num[mid]*num[mid+1]%MOD)%MOD;
}
void build(int rt,int l,int r) {
if (l==r) {
sum[rt]=num[l],sa[rt]=sb[rt]=(ll)0;
return ;
}
int mid=(l+r)>>1;
build(lson),
build(rson),
pushup(rt,mid);
}
void modify(int rt,int l,int r,int pos,ll val) {
if (l==r) {
sum[rt]=val;
return ;
}
int mid=(l+r)>>1;
if (pos<=mid) modify(lson,pos,val);
else modify(rson,pos,val);
pushup(rt,mid);
}
pa qa(int rt,int l,int r,int L,int R) {//sa,sum
if (L<=l&&r<=R) return pa(sa[rt],sum[rt]);
int mid=(l+r)>>1;
if (R<=mid) return qa(lson,L,R);
else if (mid<L) return qa(rson,L,R);
else {
pa t1=qa(lson,L,mid),t2=qa(rson,mid+1,R);
return pa(((t1.first+t2.first)%MOD+(t1.second*t2.second)%MOD)%MOD,(t1.second+t2.second)%MOD);
}
}
pa qb(int rt,int l,int r,int L,int R) {//sb,sum
if (L<=l&&r<=R) return pa(sb[rt],sum[rt]);
int mid=(l+r)>>1;
if (R<=mid) return qb(lson,L,R);
else if (mid<L) return qb(rson,L,R);
else {
pa t1=qb(lson,L,mid),t2=qb(rson,mid+1,R);
return pa(((t1.first+t2.first)%MOD+(num[mid]*num[mid+1])%MOD)%MOD,(t1.second+t2.second)%MOD);
}
}
int main() {
// freopen("Challenge 4.in","r",stdin);
n=read(),m=read();
for (register int i=1;i<=n;++i) num[i]=(ll)read();
build(root);
for (register int i=1;i<=m;++i) {
char ss;
while (!isalpha(ss=getchar()));
if (ss=='M') {
int pos=read();
num[pos]=(ll)read();//!!!
modify(root,pos,num[pos]);
}
else if (ss=='Q') {
int L=read(),R=read();
printf("%lld\n",(qa(root,L,R).first+MOD)%MOD);
}
else {
int L=read(),R=read();
printf("%lld\n",(qb(root,L,R).first+MOD)%MOD);
}
}
return 0;
}