--Segment Tree--
At the beginning, I learn it from OI-wiki
Before the part of 【优化】, I read it easily and use it to be accepted by the segment 1
segment 1
#include<iostream>
#define ll long long
#define LOCAL
using namespace std;
const ll MAXN=1E6;
ll itv[MAXN];
ll st[MAXN];
ll lztg[MAXN]; //lztg-->lazy tag
ll read(){
ll c=getchar();
ll x=0,f=1;
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;
}
void buildst(ll s, ll d, ll p){ //s-->start ; d-->end ;
if (s==d) {st[p]=itv[s];return ;}
ll m=s+((d-s)>>1);
buildst(s,m,2*p);
buildst(m+1,d,2*p+1);
st[p]=st[2*p]+st[2*p+1];
return ;
}
void itvadd(ll l,ll r,ll s,ll d,ll c,ll p){ //c--> the number to be added
if (r<s || l>d) return ;
if (l<=s && r>=d){
st[p]+=c*(d-s+1);
lztg[p]+=c;
return ;
}
ll m=s+((d-s)>>1);
if (lztg[p] && s!=d){
st[2*p]+=(m-s+1)*lztg[p];st[2*p+1]+=(d-m)*lztg[p];
lztg[2*p]+=lztg[p];lztg[2*p+1]+=lztg[p];
lztg[p]=0;
}
if (l<=m) itvadd(l,r,s,m,c,2*p);
if (r>m) itvadd(l,r,m+1,d,c,2*p+1);
st[p]=st[2*p]+st[2*p+1];
return ;
}
ll getsum(ll l,ll r,ll s,ll d,ll p){
if (r<s || l>d) return 0;
if (l<=s && r>=d) return st[p];
ll m=s+((d-s)>>1);
if (lztg[p] && s!=d){
st[2*p]+=(m-s+1)*lztg[p];st[2*p+1]+=(d-m)*lztg[p];
lztg[2*p]+=lztg[p];lztg[2*p+1]+=lztg[p];
lztg[p]=0;
}
return (l<=m?getsum(l,r,s,m,2*p):0)+(r>m?getsum(l,r,m+1,d,2*p+1):0);
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif
ll n=read(),m=read();
for (int i=1;i<=n;++i) itv[i]=read();
buildst(1,n,1);
// cout<<st[1]<<endl;
while(m--){
ll cmd=read();
// cout<<cmd<<endl;
if (cmd==1){
ll x=read(),y=read();
ll k=read();
itvadd(x,y,1,n,k,1);
// cout<<st[1]<<endl;
}
else{
ll x=read(),y=read();
printf("%lld\n",getsum(x,y,1,n,1));
// cout<<__LINE__<<endl;
}
}
return 0;
}
However, I encountered some difficulties in the Segment2
1st. I don't to settle with the compatibility between multiply and add. Afterwards, I maintained the uniqueness of lazytag (multiply or add). Even though, I have to make addpushdown and multiplypushdown functions to implement it. As a result, Runtime error.
2nd. And then, I begin to implement it by non-recursion. However, It's still RE!!!
3rd. At last, after getting the advice of Kang and reference to answer, I make a pushdown function and define the sequence of multiply and add (This is the decisive optimization)
#include<iostream>
#include<stack>
#define ll long long
#define LOCAL
using namespace std;
const ll MAXN=1E6;
ll P;
ll itv[MAXN];
ll st[MAXN];
ll lztg[MAXN]={0}; //lztg-->lazy tag
ll lztgm[MAXN];
ll read(){
ll c=getchar();
ll x=0,f=1;
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;
}
void buildst(ll s, ll d, ll p){ //s-->start ; d-->end ;
if (s==d) {st[p]=itv[s];return ;}
ll m=s+((d-s)>>1);
buildst(s,m,2*p);
buildst(m+1,d,2*p+1);
st[p]=st[2*p]+st[2*p+1];
return ;
}
//定义先乘后加
void pushdown(ll s,ll d,ll p){
if (s==d) return ;
ll m=s+((d-s)>>1);
st[2*p]=(st[2*p]*lztgm[p]+lztg[p]*(m-s+1))%P;st[2*p+1]=(st[2*p+1]*lztgm[p]+lztg[p]*(d-m))%P;
lztgm[2*p]=lztgm[2*p]*lztgm[p]%P;lztg[2*p]=(lztg[2*p]*lztgm[p]+lztg[p])%P;
lztgm[2*p+1]=lztgm[2*p+1]*lztgm[p]%P;lztg[2*p+1]=(lztg[2*p+1]*lztgm[p]+lztg[p])%P;
lztgm[p]=1;lztg[p]=0;
return ;
}
void itvadd(ll l,ll r,ll s,ll d,ll c,ll p){
if (r<s || l>d) return ;
if (l<=s && r>=d) {
st[p]=(st[p]+c*(d-s+1))%P;
lztg[p]=(lztg[p]+c)%P;
return ;
}
pushdown(s,d,p);
ll m=s+((d-s)>>1);
if (l<=m) itvadd(l,r,s,m,c,2*p);
if (r>m) itvadd(l,r,m+1,d,c,2*p+1);
st[p]=(st[2*p]+st[2*p+1])%P;
return ;
}
void itvmul(ll l,ll r,ll s,ll d,ll c,ll p){
if (r<s || l>d) return ;
if (l<=s && r>=d) {
st[p]=st[p]*c%P;
lztgm[p]=lztgm[p]*c%P;
lztg[p]=lztg[p]*c%P;
return ;
}
pushdown(s,d,p);
ll m=s+((d-s)>>1);
if (l<=m) itvmul(l,r,s,m,c,2*p);
if (r>m) itvmul(l,r,m+1,d,c,2*p+1);
st[p]=(st[2*p]+st[2*p+1])%P;
return ;
}
ll getsum(ll l,ll r,ll s,ll d,ll p){
if (r<s || l>d) return 0;
if (l<=s && r>=d) return st[p];
pushdown(s,d,p);
ll m=s+((d-s)>>1);
return (l<=m?getsum(l,r,s,m,2*p):0)%P+(r>m?getsum(l,r,m+1,d,p*2+1):0)%P;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif
for (int i=0;i<MAXN;++i) lztgm[i]=1;
ll n=read(),m=read();
P=read();
for (int i=1;i<=n;++i) itv[i]=read();
buildst(1,n,1);
// cout<<P<<endl;
// cout<<st[1]<<endl;
while(m--){
ll cmd=read();
// cout<<cmd<<endl;
if (cmd==1){
ll x=read(),y=read(),k=read();
itvmul(x,y,1,n,k,1);
}
if (cmd==2){
ll x=read(),y=read(),k=read();
itvadd(x,y,1,n,k,1);
}
if (cmd==3){
ll x=read(),y=read();
// cout<<P<<endl;
printf("%lld\n",getsum(x,y,1,n,1)%P);
// cout<<__LINE__<<endl;
}
}
return 0;
}
1. 将重复性比较高的代码写成函数
2. 做比较大的决定或改变之前要分析时间复杂度,不要想到就做,要分析到底该不该做后在做!!!
3. 思路中,要减少不确定性因素,增加确定性,即使是假设,也要分析 多种假设之间的异同,并找到最优的假设!!!