描述
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
幼儿园里的小朋友们正在和老师玩一个有趣的游戏。小朋友们被分成了 N 小组,初始时第i小组的人数为 ai 。老师先选定一些编号在[l,r]内的小组,然后开始与这段连续的小组的一次游戏。游戏是这样进行的:每次游戏分成若干轮,每一轮老师转过身去,[l,r]中的小组的小朋友们需要在这时通过选举选出 3 个来自不同小组的小朋友上前领老师的糖果, 并且为了体现公平,以下情形被视为犯规:某一轮选出了 3 个人领糖果,而后来这 3 个人又在同一 轮被选举出来领糖果。现在老师会不时地问你:假如他与编号在[l,r]内的小组做一次游戏,则最多能玩多少轮。小组不是固定的,人数会不时发生变化。
输入
第一行两个整数 N, M ,分别为小组数目和事件数目。
第二行 N 个整数表示 ai 。
接下来 M 行,每行描述一个事件。事件为以下两类之一(第一个数为事件类型) :
1 l r 表示询问
2 id p 表示第id 个小组的人数变成 p 。
输出
对于每一个询问操作,输出一行一个整数为答案。因为答案可能很大,只需要输出其对 1e9 + 7 取模后的结果即可。
样例输入 [复制]
5 3
1 2 3 4 5
1 1 3
2 1 2
1 1 3
样例输出 [复制]
6
12
提示
数据约束
对于 30%的数据, N, M <= 50 。
对于 50%的数据, N, M <= 5000 。
对于 100%的数据,1<= N, M<=100000,1<= ai, p <=10^9+ 7 。
提示
注意乘法溢出问题
///////////////////////////////////////////////////////////////////////////////////////////////
线段树水题啊。。
实在不懂 合并操作和维护值的类型的,评论区留言吧。。。。。
(不写快速乘可以水过去,而且快得多。。。)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define lc (p<<1)
#define rc ((p<<1)|1)
const int maxn=1e5+10,mod=1e9+7;
inline int ksc(int a,int b){
if(a<b)swap(a,b);
int ans=0;
while(b){
if(b&1)ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
struct T{
int l,r;
int s[3];
}t[maxn<<2];
int a[maxn];
inline T merge(T l,T r){
T ans;
ans.l=l.l,ans.r=r.r;
ans.s[0]=l.s[0]+r.s[0];ans.s[0]%=mod;
ans.s[1]=ksc(l.s[0],r.s[0])+l.s[1]+r.s[1]; ans.s[1]%=mod;
ans.s[2]=ksc(l.s[1],r.s[0])+ksc(l.s[0],r.s[1])+l.s[2]+r.s[2];ans.s[2]%=mod;
return ans;
}
inline void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r){
t[p].s[0]=a[l];
return;
}
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
t[p]=merge(t[lc],t[rc]);
}
inline void change(int p,int k,int v){
if(t[p].l==t[p].r){
t[p].s[0]=v;
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(k<=mid) change(lc,k,v);
else change(rc,k,v);
//cerr<<0<<" "<<t[p].l<<" "<<t[p].r<<" "<<t[p].s[2]<<endl;
t[p]=merge(t[lc],t[rc]);
//cerr<<1<<" "<<t[p].l<<" "<<t[p].r<<" "<<t[p].s[2]<<endl;
}
inline T query(int p,int ql,int qr){
if(t[p].l>=ql&&t[p].r<=qr){
return t[p];
}
int mid=(t[p].l+t[p].r)>>1;
if(qr<=mid) return query(lc,ql,qr);
else if (ql>mid) return query(rc,ql,qr);
else return merge(query(lc,ql,qr),query(rc,ql,qr));
}
signed main(){
int n,m;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
int a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
if(a==1){
printf("%lld\n",query(1,b,c).s[2]);
}
else{
change(1,b,c);
}
}
return 0;
}