各种板子

线段树

区间修改,区间求和

https://www.luogu.org/problemnew/show/P3372

代码

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

typedef long long ll;

const int maxn=100000+10;

ll a[maxn];
ll add[maxn<<2],tree[maxn<<2];

void pushup(int rt){
     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}

void build(int l,int r,int rt){
     if(l==r){
        tree[rt]=a[l];
        return ;
     }
     int mid=(l+r)>>1;
     build(l,mid,rt<<1);
     build(mid+1,r,rt<<1|1);
     pushup(rt);
}

void pushdown(int rt,int ln,int rn){
     if(add[rt]){
        add[rt<<1]+=add[rt];
        add[rt<<1|1]+=add[rt];
        tree[rt<<1]+=add[rt]*ln;
        tree[rt<<1|1]+=add[rt]*rn;
        add[rt]=0;
     }
}

void update(int l,int r,int rt,int L,int R,int c){
     if(l>=L&&r<=R){
        add[rt]+=c;
        tree[rt]+=c*(r-l+1);
        return ;
     }
     int mid=(l+r)>>1;
     pushdown(rt,mid-l+1,r-mid);
     if(L<=mid) update(l,mid,rt<<1,L,R,c);
     if(R>mid) update(mid+1,r,rt<<1|1,L,R,c);
     pushup(rt);
}

ll ask(int l,int r,int rt,int L,int R){
   if(l>=L&&r<=R){
    return tree[rt];
   }
   int mid=(l+r)>>1;
   pushdown(rt,mid-l+1,r-mid);
   ll ans=0;
   if(L<=mid) ans+=ask(l,mid,rt<<1,L,R);
   if(R>mid) ans+=ask(mid+1,r,rt<<1|1,L,R);
   return ans;
}

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(1,n,1);
    int op,x,y,k;
    while(m--){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d%d",&x,&y,&k);
            update(1,n,1,x,y,k);
        }
        else {
            scanf("%d%d",&x,&y);
            printf("%lld
",ask(1,n,1,x,y));
        }
    }
return 0;
}

二分

 二分,第一个大于x

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=1000;

int a[maxn];

int main(){
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int l=1;
    int r=n;
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[mid]>5){若要查找最后一个小于x的改为>=,输出r;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%d ",l);
return 0;
}

可以这样理解,查找大于等于的,判断那里就是大于等于,查找小于等于的判断那里是大于


二维前缀和

垃圾炸弹

https://www.lydsy.com/JudgeOnline/problem.php?id=1218

代码

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=5050;

int sum[maxn][maxn];

int main(){
    int n,r;
    int x,y,w;
    scanf("%d%d",&n,&r);
    for (int i=1;i<=n;i++){
        scanf("%d%d%d",&x,&y,&w);
        sum[x+1][y+1]=w;
    }
    for (int i=1;i<=5001;i++) sum[1][i]=sum[1][i-1]+sum[1][i];
    for (int i=1;i<=5001;i++) sum[i][1]=sum[i-1][1]+sum[i][1];
    for (int i=2;i<=5001;i++){
        for (int j=2;j<=5001;j++){
            sum[i][j]=sum[i-1][j]+sum[i][j-1]+sum[i][j]-sum[i-1][j-1];
        }
    }

    int ans=0;
    for (int i=r;i<=5001;i++){
        for (int j=r;j<=5001;j++){
            ans=max(ans,sum[i][j]-sum[i-r][j]-sum[i][j-r]+sum[i-r][j-r]);
        }
    }
    printf("%d",ans);
return 0;
}

前缀和

https://www.luogu.org/recordnew/show/11207133

#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;

const int maxn=100000+10;

ll sum[maxn];

int main(){
    int n,k,y;
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++){
        scanf("%d",&y);
        sum[i]=sum[i-1]+y;
    }
    ll ans=0;
    for (int i=k;i<=n;i++) ans+=(sum[i]-sum[i-k]);
    printf("%lld",ans);
return 0;
}

快速幂

https://www.luogu.org/problemnew/show/P1226

#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;
ll mod;

ll quickmod(ll a,ll b,ll mod){
   ll ans=1%mod;
   for (;b;b>>=1){
    if(b&1) ans=ans*a%mod;
    a=a*a%mod;
   }
   return ans%mod;
}

int main(){
    ll a,b;
    scanf("%lld%lld%lld",&a,&b,&mod);
    printf("%lld^%lld mod %lld=%lld",a,b,mod,quickmod(a,b,mod));
return 0;
}
原文地址:https://www.cnblogs.com/lmjer/p/9715575.html