写在前面:我是一只蒟蒻。。。
快速幂模板:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll b,p,k; 5 int main(){ 6 scanf("%lld%lld%lld",&b,&p,&k); 7 ll c=b,d=p; 8 ll ans=1; 9 while(p){ 10 if(p&1){ 11 ans=(ans*b)%k; 12 } 13 b=(b*b)%k; 14 p>>=1; 15 } 16 // cout<<c<<"^"<<d<<" mod "<<k<<"="<<ans%k; 17 printf("%d ",ans%k); 18 return 0; 19 }
线段树模板:
#include<bits/stdc++.h> #define ll long long const int N=5e6+8; using namespace std; ll n,m,tag[N],ans[N],a[N]; ll ls(ll x){ return x<<1; }//左儿子扩展 (x*2) ll rs(ll x){ return x<<1|1; }//右儿子扩展(x*2+1) void up(ll x){ ans[x]=ans[ls(x)]+ans[rs(x)]; }// 求出当前点的总和值 void build(ll l,ll r,ll p){ if(l==r){ ans[p]=a[l]; return; } ll mid=(l+r)>>1; build(l,mid,ls(p));//左儿子建树 build(mid+1,r,rs(p));//右儿子建树 up(p);//进行整合 } void f(ll l,ll r,ll p,ll k){//k是懒(延迟)标记的数值 tag[p]+=k; ans[p]+=(r-l+1)*k; }//tag[]懒标记点。 void down(ll l,ll r,ll p){ ll mid=(l+r)>>1; f(l,mid,ls(p),tag[p]);//左传 f(mid+1,r,rs(p),tag[p]);//右传 tag[p]=0;//懒标记传递结束,清零 } void xg(ll xl,ll xr,ll l,ll r,ll p,ll k){//修改操作 if(l>=xl&&xr>=r){//当前区间被所查询的区间包含 ans[p]+=(r-l+1)*k; tag[p]+=k; return ; } down(l,r,p);//懒坐标传递 ll mid=(l+r)>>1; if(xl<=mid){ xg(xl,xr,l,mid,ls(p),k); } if(xr>mid){ xg(xl,xr,mid+1,r,rs(p),k); } up(p);//更新该节点 } ll query(ll gl,ll gr,ll l,ll r,ll p){ ll an=0; if(gl<=l&&gr>=r){ return ans[p]; } ll mid=(l+r)>>1; down(l,r,p); if(gl<=mid){ an+=query(gl,gr,l,mid,ls(p)); } if(gr>mid){ an+=query(gl,gr,mid+1,r,rs(p)); } return an; } ll fl,x,y,z; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } build(1,n,1); for(int i=1;i<=m;i++){ scanf("%d",&fl); if(fl==1){ scanf("%lld%lld%lld",&x,&y,&z); xg(x,y,1,n,1,z); } if(fl==2){ scanf("%lld%lld",&x,&y); printf("%lld ",query(x,y,1,n,1)); } } return 0; }
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=5e6+7; ll ans[N],a[N],at[N],ml[N]; ll fl,n,m,P,x,y,z; ll ls(ll x){ return x<<1; } ll rs(ll x){ return x<<1|1; } void up(ll p){ ans[p]=(ans[ls(p)]+ans[rs(p)])%P; } void build(ll l,ll r,ll p){ at[p]=0; ml[p]=1; if(l==r){ ans[p]=a[l]; return; } ll mid=(l+r)>>1; build(l,mid,ls(p)); build(mid+1,r,rs(p)); up(p); } void down(ll l,ll r,ll p){ ml[ls(p)]=(ml[ls(p)]*ml[p])%P; ml[rs(p)]=(ml[rs(p)]*ml[p])%P; at[ls(p)]=(at[ls(p)]*ml[p])%P; at[rs(p)]=(at[rs(p)]*ml[p])%P; ans[ls(p)]=(ans[ls(p)]*ml[p])%P; ans[rs(p)]=(ans[rs(p)]*ml[p])%P; ml[p]=1;//乘懒标记传递完成,清零处理,乘法优先于加法,所以先计算乘法再计算加法 ll mid=(l+r)>>1; at[ls(p)]=(at[ls(p)]+at[p])%P; at[rs(p)]=(at[rs(p)]+at[p])%P; ans[ls(p)]=(ans[ls(p)]+(mid-l+1)*at[p])%P; ans[rs(p)]=(ans[rs(p)]+(r-mid)*at[p])%P; at[p]=0; } void xg(ll gl,ll gr,ll l,ll r,ll p,ll k){ if(l>=gl&&gr>=r){ at[p]=(k+at[p])%P; ans[p]=((r-l+1)*k+ans[p])%P; return ; } down(l,r,p); ll mid=(l+r)>>1; if(gl<=mid){ xg(gl,gr,l,mid,ls(p),k); } if(gr>mid){ xg(gl,gr,mid+1,r,rs(p),k); } up(p); }//修改+; void ch(ll cl,ll cr,ll l,ll r,ll p,ll k){ if(l>=cl&&r<=cr){ ml[p]=(ml[p]*k)%P; at[p]=(at[p]*k)%P; ans[p]=(ans[p]*k)%P; return ; } down(l,r,p); ll mid=(l+r)>>1; if(cl<=mid){ ch(cl,cr,l,mid,ls(p),k); } if(cr>mid){ ch(cl,cr,mid+1,r,rs(p),k); } up(p); }//修改*; ll query(ll al,ll ar,ll l,ll r,ll p){ ll an=0; if(al<=l&&ar>=r){ return ans[p]%P; } down(l,r,p); ll mid=(l+r)>>1; if(al<=mid){ an=an+query(al,ar,l,mid,ls(p)); } if(ar>mid){ an=an+query(al,ar,mid+1,r,rs(p)); } return an%P; } int main(){ scanf("%lld%lld%lld",&n,&m,&P); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); build(1,n,1); for(int i=1;i<=m;i++){ scanf("%lld",&fl); if(fl==1){ scanf("%lld%lld%lld",&x,&y,&z); ch(x,y,1,n,1,z); } if(fl==2){ scanf("%lld%lld%lld",&x,&y,&z); xg(x,y,1,n,1,z); } if(fl==3){ scanf("%lld%lld",&x,&y); printf("%lld ",(query(x,y,1,n,1))%P); } } return 0; }
离散化处理:
1 for(int i=1;i<=n;i++){ 2 scan(a[i].x);scan(a[i].y);scan(a[i].e); 3 book[++tot]=a[i].x; 4 book[++tot]=a[i].y; 5 } 6 sort(book,book+tot); 7 int reu=unique(book,book+tot)-book; 8 for(int i=1;i<=n;i++){ 9 a[i].x=lower_bound(book,book+reu,a[i].x)-book; 10 a[i].y=lower_bound(book,book+reu,a[i].y)-book; 11 }