虽然代码是对的,但是最慢的点正好1.00s,开O2也没用还是1.00s,要是评测姬有波动会T掉一个点
#include <iostream>
using namespace std;
long long p;
const int memory_size=4e5;//分配内存数量
template<class data_type>
class segment_tree
{
private:
template<class node_type>
struct node
{
int l;
int r;
node_type sum;
node_type taga;//加法延时操作
node_type tagb;//乘法延时操作
};
node<data_type> t[memory_size];
inline void build(int id,int l,int r,data_type array[])
{
t[id].l=l;
t[id].r=r;
t[id].taga=0;
t[id].tagb=1;
if(l==r)
{
t[id].sum=array[l];
return;
}
int mid=(l+r)/2;
build(id*2,l,mid,array);
build(id*2+1,mid+1,r,array);
t[id].sum=t[id*2].sum+t[id*2+1].sum;
return;
}
//进行id号节点的未完成操作
inline void push_down(int id)
{
//cout<<id<<"号节点标记下传\n";
if(t[id].l!=t[id].r)
{
t[id*2].tagb*=t[id].tagb;
t[id*2].taga*=t[id].tagb;
t[id*2].taga+=t[id].taga;
t[id*2+1].tagb*=t[id].tagb;
t[id*2+1].taga*=t[id].tagb;
t[id*2+1].taga+=t[id].taga;
t[id*2].taga%=p;
t[id*2].tagb%=p;
t[id*2+1].taga%=p;
t[id*2+1].tagb%=p;
}
t[id].sum=((t[id].sum*t[id].tagb)+t[id].taga*(t[id].r-t[id].l+1))%p;
t[id].taga=0;
t[id].tagb=1;
return ;
}
inline void add(int id,int l,int r,data_type x)
{
push_down(id);
if(t[id].l==l&&t[id].r==r)
{
t[id].taga+=x;
return ;
}
t[id].sum+=(r-l+1)*x;
int mid=(t[id].l+t[id].r)/2;
bool b1=(t[id].l<=l&&l<=mid),b2=(mid+1<=r&&r<=t[id].r);
if(b1&&!b2)
add(id*2,l,r,x);
else if(!b1&&b2)
add(id*2+1,l,r,x);
else if(b1&&b2)
{
add(id*2,l,mid,x);
add(id*2+1,mid+1,r,x);
}
return ;
}
inline data_type request(int id,int l,int r)
{
push_down(id);
if(t[id].l==l&&t[id].r==r)
return t[id].sum%p;
int mid=(t[id].l+t[id].r)/2;
bool b1=(t[id].l<=l&&l<=mid),b2=(mid+1<=r&&r<=t[id].r);
if(b1&&!b2)
return request(id*2,l,r)%p;
else if(!b1&&b2)
return request(id*2+1,l,r)%p;
else if(b1&&b2)
return (request(id*2,l,mid)+request(id*2+1,mid+1,r))%p;
}
inline void mul(int id,int l,int r,data_type x)
{
push_down(id);
if(t[id].l==l&&t[id].r==r)
{
t[id].tagb*=x;
t[id].taga*=x;
return;
}
t[id].sum+=request(id,l,r)*(x-1);
int mid=(t[id].l+t[id].r)/2;
bool b1=(t[id].l<=l&&l<=mid),b2=(mid+1<=r&&r<=t[id].r);
if(b1&&!b2)
mul(id*2,l,r,x);
else if(!b1&&b2)
mul(id*2+1,l,r,x);
else if(b1&&b2)
{
mul(id*2,l,mid,x);
mul(id*2+1,mid+1,r,x);
}
return ;
}
inline void tabs(int tab){for(int i=1;i<=tab;i++)cout<<" ";}
inline void print(int id,int tab)
{
tabs(tab);
cout<<"第"<<id<<"号节点(左端点:"<<t[id].l<<",右端点:"<<t[id].r<<",区间和:"<<t[id].sum<<",加法延时标记:"<<t[id].taga<<",乘法延时标记:"<<t[id].tagb<<"\n";
if(t[id].l!=t[id].r)
{
print(id*2,tab+1);
print(id*2+1,tab+1);
}
return ;
}
public:
inline void build(int length,data_type array[])
{
build(1,1,length,array);
}
inline void add(int l,int r,data_type x)
{
add(1,l,r,x);
}
inline data_type request(int l,int r)
{
return request(1,l,r);
}
inline void mul(int l,int r,data_type x)
{
mul(1,l,r,x);
}
inline void print()
{
print(1,0);
}
};
segment_tree<long long> t;
long long a[100005];
int main()
{
int n,m;
cin>>n>>m>>p;
for(int i=1;i<=n;i++)
cin>>a[i];
t.build(n,a);
//t.print();
for(int i=1;i<=m;i++)
{
int op;
cin>>op;
if(op==1)
{
int l,r,x;
cin>>l>>r>>x;
t.mul(l,r,x);
}
else if(op==2)
{
int l,r,x;
cin>>l>>r>>x;
t.add(l,r,x);
//t.print();
}
else if(op==3)
{
int l,r;
cin>>l>>r;
cout<<t.request(l,r)<<"\n";
//t.print();
}
}
}
或者有没有一种可能,我是说一种可能,我的乘法操作因为每次更新区间和都要调用一次查询函数,导致总时间复杂度是O(log2n) ,因为常数小数据弱所以过了,但是正确的复杂度应该少一只 log 呢...?