修改儿子之前pushdown,修改儿子之后update,查询儿子之前pushdown,多种操作理清楚先后顺序
经测试inline基本没用
注意避免中间结果爆int
数组开N*4
多种操作可以尽量合成一个函数,减少代码量
EOJ 3393
区间求和、最大值、最小值 支持区间加法和区间覆盖
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> using namespace std; #define LL long long #define rep(i,n) for(int i=1;i<=n;i++) #define pLL pair<long long,long long> #define st first #define nd second #define mp make_pair const int N=5e5+7; const LL inf=7e18; int n,q; int a[N]; LL tree[N*4][3]; LL tag1[N*4],tag2[N*4]; int len[N*4]; inline LL max(LL x,LL y){ if(x>y)return x; return y; } inline LL min(LL x,LL y){ if(x<y)return x; return y; } inline void update(int node){ tree[node][0]=tree[node<<1][0]+tree[node<<1^1][0]; tree[node][1]=max(tree[node<<1][1],tree[node<<1^1][1]); tree[node][2]=min(tree[node<<1][2],tree[node<<1^1][2]); } void build(int node,int l,int r){ tag1[node]=tag2[node]=inf; len[node]=r-l+1; if(l==r){ tree[node][0]=tree[node][1]=tree[node][2]=a[l]; return; } int mid=(l+r)>>1; build(node<<1,l,mid); build(node<<1^1,mid+1,r); update(node); } inline pair<LL,pLL> merge(pair<LL,pLL> a,pair<LL,pLL> b){ return mp(a.st+b.st,mp( max(a.nd.st,b.nd.st) , min(a.nd.nd,b.nd.nd) ) ); } inline void maketag(int node,LL a,LL b){ if(b!=inf){ tree[node][0]=b*len[node]; tree[node][1]=b; tree[node][2]=b; tag1[node]=inf; tag2[node]=b; } if(a!=inf){ tree[node][0]+=a*len[node]; tree[node][1]+=a; tree[node][2]+=a; if(tag1[node]==inf)tag1[node]=0; tag1[node]+=a; } } inline void pushdown(int node){ maketag(node<<1,tag1[node],tag2[node]); maketag(node<<1^1,tag1[node],tag2[node]); tag1[node]=tag2[node]=inf; } inline void change(int node,int L,int R,int l,int r,LL a,LL b){ if(R<l||L>r)return ; if(L>=l&&R<=r){ maketag(node,a,b); return ; } if(tag1[node]!=inf||tag2[node]!=inf)pushdown(node); int mid=(L+R)>>1; change(node<<1,L,mid,l,r,a,b); change(node<<1^1,mid+1,R,l,r,a,b); update(node); } inline pair<LL,pLL> query(int node,int L,int R,int l,int r){ if(R<l||L>r)return mp(0,mp(-inf,inf)); if(L>=l&&R<=r){ return mp(tree[node][0],mp(tree[node][1],tree[node][2])); } int mid=(L+R)>>1; pushdown(node); return merge(query(node<<1,L,mid,l,r),query(node<<1^1,mid+1,R,l,r)); } int main(){ scanf("%d",&n); rep(i,n)scanf("%d",&a[i]); build(1,1,n); scanf("%d",&q); while(q--){ int f,l,r; scanf("%d%d%d",&f,&l,&r); if(f==3){ pair<LL,pLL> ans=query(1,1,n,l,r); printf("%lld %lld %lld\n",ans.st,ans.nd.st,ans.nd.nd); } if(f==1){ int v; scanf("%d",&v); change(1,1,n,l,r,v,inf); } if(f==2){ int v; scanf("%d",&v); change(1,1,n,l,r,inf,v); } } }
ZOJ 3998
区间求积 支持区间乘法和区间求幂
乘方的取模利用费马小定理的推论:a^n ≡ a^ (n mod φ(p))(modp),p为质数时φ(p)=p-1。其他基本和上一题相同。
快速幂不要用递归!!!
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> using namespace std; #define LL long long #define rep(i,n) for(int i=1;i<=n;i++) const int N=1e5+7; const int mod=1e9+7; int n,a[N],tree[N*4],tag1[N*4],tag2[N*4],len[N*4]; inline void update(int node){ tree[node]=1LL*tree[node<<1]*tree[node<<1|1]%mod; } inline int po(int x,int y){ int res=1; while(y){ if(y&1)res=1LL*res*x%mod; y>>=1; x=1LL*x*x%mod; } return res; } inline void maketag(int node,int v,int k){ tree[node]=1LL*po(tree[node],k)*po(v,len[node])%mod; tag1[node]=1LL*po(tag1[node],k)*v%mod; tag2[node]=1LL*tag2[node]*k%(mod-1); } inline void push_down(int node){ maketag(node<<1,tag1[node],tag2[node]); maketag(node<<1|1,tag1[node],tag2[node]); tag1[node]=tag2[node]=1; } inline int query(int node,int L,int R,int l,int r){ if(l>R||r<L)return 1; if(L>=l&&R<=r)return tree[node]; push_down(node); int mid=(L+R)>>1; return 1LL*query(node<<1,L,mid,l,r)*query(node<<1|1,mid+1,R,l,r)%mod; } inline void change(int node,int L,int R,int l,int r,int v,int k){ if(l>R||r<L)return; if(L>=l&&R<=r){ maketag(node,v,k); return ; } if(tag1[node]!=1||tag2[node]!=1)push_down(node); int mid=(L+R)>>1; change(node<<1,L,mid,l,r,v,k); change(node<<1|1,mid+1,R,l,r,v,k); update(node); } void build(int node,int l,int r){ tag1[node]=tag2[node]=1; len[node]=r-l+1; if(l==r){ tree[node]=a[l]; return; } int mid=(l+r)>>1; build(node<<1,l,mid); build(node<<1|1,mid+1,r); update(node); } int main() { int t,q; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&q); rep(i,n)scanf("%d",&a[i]); build(1,1,n); while(q--){ int op,l,r,v; scanf("%d%d%d",&op,&l,&r); if(op==1){ scanf("%d",&v); change(1,1,n,l,r,v,1); } if(op==2){ scanf("%d",&v); change(1,1,n,l,r,1,v); } if(op==3){ printf("%d\n",query(1,1,n,l,r)); } } } //system("pause"); }
洛谷 3373
区间求和 支持区间加法和区间乘法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> using namespace std; #define LL long long #define rep(i,n) for(int i=1;i<=n;i++) #define pLL pair<long long,long long> #define st first #define nd second #define mp make_pair const int N=1e5+7; const LL inf=7e18; int n,q; int a[N]; LL tree[N*4],add[N*4],mul[N*4],len[N*4],p; void update(int node){ tree[node]=(tree[node<<1]+tree[node<<1^1])%p; } void build(int node,int l,int r){ add[node]=0; mul[node]=1; len[node]=r-l+1; if(l==r){ tree[node]=a[l]; return; } int mid=(l+r)>>1; build(node<<1,l,mid); build(node<<1^1,mid+1,r); update(node); } void maketag(int node,LL a,LL b){ tree[node]=(a*tree[node]%p + b*len[node]%p)%p; add[node]=(a*add[node]%p + b )%p; mul[node]=mul[node]*a%p; } void pushdown(int node){ maketag(node<<1,mul[node],add[node]); maketag(node<<1^1,mul[node],add[node]); mul[node]=1; add[node]=0; } void change(int node,int L,int R,int l,int r,LL a,LL b){ if(R<l||L>r)return ; if(L>=l&&R<=r){ maketag(node,a,b); return; } int mid=(L+R)>>1; pushdown(node); change(node<<1,L,mid,l,r,a,b); change(node<<1^1,mid+1,R,l,r,a,b); update(node); } LL query(int node,int L,int R,int l,int r){ if(R<l||L>r)return 0; if(L>=l&&R<=r)return tree[node]; pushdown(node); int mid=(L+R)>>1; return (query(node<<1,L,mid,l,r)+query(node<<1^1,mid+1,R,l,r))%p; } int main(){ scanf("%d%d%d",&n,&q,&p); rep(i,n)scanf("%d",&a[i]); build(1,1,n); while(q--){ int f,l,r; scanf("%d%d%d",&f,&l,&r); if(f==3){ printf("%lld\n",query(1,1,n,l,r)); } if(f==2){ int v; scanf("%d",&v); change(1,1,n,l,r,1,v); } if(f==1){ int v; scanf("%d",&v); change(1,1,n,l,r,v,0); } } }