线段树专题

先来一个通用的模板

typedef long long ll;
const int maxn = 2e5 + 10;
struct node
{
    ll x,minn,maxx,sum,f;
}tree[4 * maxn];   //结构体开4倍空间
ll n,a[maxn],m;
ll x,y,s,op;

void build(int x,int l,int r)  //建树  build(1,1,n);
{
    if(l == r)
    {
        tree[x].x = a[l];
        tree[x].sum = a[l];
        //tree[x].maxx = a[l];
        //tree[x].minn = a[l];
        return;
    }
    int mid = (l + r) / 2;
    build(x * 2,l,mid);
    build(x * 2 + 1,mid + 1,r);
    //tree[x].maxx = max(tree[x * 2].maxx,tree[x * 2 + 1].maxx);
    //tree[x].minn = max(tree[x * 2].minn,tree[x * 2 + 1].minn);
    tree[x].sum = tree[x * 2].sum + tree[x * 2 + 1].sum;
}

void down(int x,int l,int r)    //懒惰标记
{
    int mid = (l + r) / 2;
    tree[x * 2].f += tree[x].f;
    tree[x * 2 + 1].f += tree[x].f;
    tree[x * 2].sum += tree[x].f * (mid - l + 1);
    tree[x * 2 + 1].sum += tree[x].f * (r - mid);
    //tree[x * 2].maxx += tree[x].f;
    //tree[x * 2 + 1].maxx += tree[x].f;
    //tree[x * 2].minn += tree[x].f;
    //tree[x * 2 + 1].minn += tree[x].f;
    tree[x].f = 0;
}

void add1(int x,int l,int r,int pos,int s)   //单点修改  add(1,1,n,x,s)
{
    if(l == r)
    {
        tree[x].x += s;
        tree[x].sum += s;
        return;
    }
    if(tree[x].f) down(x,l,r);
    int mid = (l + r) / 2;
    if(pos <= mid) add1(x * 2,l,mid,pos,s);
    else add1(x * 2 + 1,mid + 1,r,pos,s);
    //tree[x].maxx = max(tree[x * 2].maxx,tree[x * 2 + 1].maxx);
    //tree[x].minn = max(tree[x * 2].minn,tree[x * 2 + 1].minn);
    tree[x].sum = tree[x * 2].sum + tree[x * 2 + 1].sum;
}

ll query(int x,int l,int r,int pos)   //单点查询   query(1,1,n,x);
{
    if(l == r) return tree[x].sum;
    if(tree[x].f) down(x,l,r);
    int mid = (l + r) / 2;
    if(pos <= mid) return query(x * 2,l,mid,pos);
    else query(x * 2 + 1,mid + 1,r,pos);
}

void add2(int x,int l,int r,int al,int ar,int s)   //区间修改   add2(1,1,n,l,r,s);
{
    if(l >= al && r <= ar)
    {
        tree[x].sum += (r - l + 1) * s; //(r-1)+1区间点的总数
        tree[x].f += s;
        return;
    }
    if(tree[x].f) down(x,l,r);
    int mid = (l + r) / 2;
    if(al <= mid) add2(x * 2,l,mid,al,ar,s);
    if(ar > mid) add2(x * 2 + 1,mid + 1,r,al,ar,s);
    //tree[x].maxx = max(tree[x * 2].maxx,tree[x * 2 + 1].maxx);
    //tree[x].minn = max(tree[x * 2].minn,tree[x * 2 + 1].minn);
    tree[x].sum = tree[x * 2].sum + tree[x * 2 + 1].sum;
}

ll query2(int x,int l,int r,int al,int ar)
{
    if(l >= al && r <= ar) return tree[x].sum; //或者是maxx/minn
    if(tree[x].f) down(x,l,r);
    int mid = (l + r) / 2;
    if(ar <= mid) return query2(x * 2,l,mid,al,ar);
    else if(al > mid) return query2(x * 2 + 1,mid + 1,r,al,ar);
    else return query2(x * 2,l,mid,al,ar) + query2(x * 2 + 1,mid + 1,r,al,ar);
}

 

上一篇:Making the Grade


下一篇:最大流(二)—— SAP算法