分块、线段树练习

1、传送门

题目大意:单点修改、区间查询

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define M 100005
int n,t,ans,m,x,y,z;
int a[M],belong[M],sum[M];
inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}
int query(int x,int y)
{
    ans=0;
    for(int i=x;i<=min(y,belong[x]*t);i++)ans+=a[i];
    for(int i=belong[x]+1;i<belong[y];i++)ans+=sum[i];
    if(belong[x]!=belong[y])
    {for(int i=(belong[y]-1)*t+1;i<=y;i++)ans+=a[i];}
    return ans;
}
int main()
{
    n=read();t=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        belong[i]=(i-1)/t+1;
        sum[belong[i]]+=a[i];
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();z=read();
        if(x==1){sum[belong[y]]+=z;a[y]+=z;};
        if(x==2)printf("%d
",query(y,z));
    }
    return 0;
}

2、传送门

题目大意:区间修改 单点查询

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define M 100005
int n,t,m,x,y,z,l,r;
int a[M],belong[M],tot[M];
inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}
int main()
{
    n=read();t=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        belong[i]=(i-1)/t+1;
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();
        if(x==1){
            l=read();r=read();z=read();
            for(int i=l;i<=min(r,belong[l]*t);i++)
            a[i]+=z;
            for(int i=belong[l]+1;i<belong[r];i++)
            tot[i]+=z;
            if(belong[l]!=belong[r])
            for(int i=(belong[r]-1)*t+1;i<=r;i++)a[i]+=z;
        }
        if(x==2)
        {
            z=read();
            printf("%d
",a[z]+tot[belong[z]]);
        }
    }
    return 0;
}

3、传送门

未完....

原文地址:https://www.cnblogs.com/zzyh/p/6961585.html