UOJ Logo zmhx2的博客

博客

线段树模板(双标记版)

2015-03-28 17:00:08 By zmhx2

线段树模板(双标记版)

#include<stdio.h>
#include<string.h>
#define INF (1<<30)
#define RIGHT (segt[cur].r)
#define LEFT (segt[cur].l)
#define SUM (segt[cur].sum)
#define MAX (segt[cur].max)
#define MIN (segt[cur].min)
#define RCHILD ((cur<<1)+1)
#define LCHILD (cur<<1)
#define TAG (segt[cur].tag)
#define TAG2 (segt[cur].tag2)
typedef struct
{
    int l, r;
    int sum, max, min;
    int tag, tag2;
} node;
node segt[10000];
int n, m, q;
int max(int a, int b)
{
    return a > b ? a : b;
}
int min(int a, int b)
{
    return a < b ? a : b;
}
void update(int cur)//更新线段树节点
{
    SUM = segt[LCHILD].sum + segt[RCHILD].sum;
    MAX = max(segt[LCHILD].max, segt[RCHILD].max);
    MIN = min(segt[LCHILD].min, segt[RCHILD].min);
}
void pushdown(int cur)//下推标记
{
    if(TAG)
    {
        segt[LCHILD].max += TAG;
        segt[LCHILD].min += TAG;
        segt[LCHILD].sum += TAG * (segt[LCHILD].r - segt[LCHILD].l + 1);
        segt[LCHILD].tag += TAG;
        segt[RCHILD].max += TAG;
        segt[RCHILD].min += TAG;
        segt[RCHILD].sum += TAG * (segt[RCHILD].r - segt[RCHILD].l + 1);
        segt[RCHILD].tag += TAG;
        TAG = 0;
    }
}
void pushdown2(int cur)//下推标记
{
    if(TAG2)
    {
        segt[LCHILD].max = TAG2;
        segt[LCHILD].min = TAG2;
        segt[LCHILD].sum = TAG2 * (segt[LCHILD].r - segt[LCHILD].l + 1);
        segt[LCHILD].tag2 = TAG2;
        segt[RCHILD].max = TAG2;
        segt[RCHILD].min = TAG2;
        segt[RCHILD].sum = TAG2 * (segt[RCHILD].r - segt[RCHILD].l + 1);
        segt[RCHILD].tag2 = TAG2;
        TAG2 = 0;
    }
}
void build(int cur, int l, int r) //建树
{
    LEFT = l;
    RIGHT = r;
    if(l >= r)return;
    build(LCHILD, l, (l + r) >> 1);
    build(RCHILD, ((l + r) >> 1) + 1, r);
}
void add(int cur, int l, int r, int val) //区间加值
{
    int mid = (LEFT + RIGHT) >> 1;
    if(LEFT >= l && RIGHT <= r)
    {
        TAG += val;
        SUM += val * (RIGHT - LEFT + 1);
        MIN += val;
        MAX += val;
        return;
    }
    pushdown(cur);
    if(l <= mid)add(LCHILD, l, r, val);
    if(r > mid)add(RCHILD, l, r, val);
    update(cur);
}
void set(int cur, int l, int r, int val) //区间设值
{
    int mid = (LEFT + RIGHT) >> 1;
    if(LEFT >= l && RIGHT <= r)
    {
        TAG2 = val;
        SUM = val * (RIGHT - LEFT + 1);
        MIN = val;
        MAX = val;
        return;
    }
    pushdown2(cur);
    if(l <= mid)set(LCHILD, l, r, val);
    if(r > mid)set(RCHILD, l, r, val);
    update(cur);
}

void modify(int cur, int x, int val) //单点修改
{
    int mid = (LEFT + RIGHT) >> 1;
    if(LEFT == x && RIGHT == x)
    {
        SUM = MAX = MIN = val;
        return;
    }
    if(x <= mid)modify(LCHILD, x, val);
    else if(x > mid)modify(RCHILD, x, val);
    update(cur);
}
int qsum(int cur, int l, int r) //区间和
{
    int mid = (LEFT + RIGHT) >> 1, rtn = 0;
    if(LEFT >= l && RIGHT <= r)
        return SUM;
    pushdown2(cur);
    if(l <= mid)rtn += qsum(LCHILD, l, r);
    if(r > mid)rtn += qsum(RCHILD, l, r);
    return rtn;
}
int qmax(int cur, int l, int r) //区间最大值
{
    int mid = (LEFT + RIGHT) >> 1, rtn = -INF;
    if(LEFT >= l && RIGHT <= r)
        return MAX;
    pushdown2(cur);
    if(l <= mid)rtn = max(rtn, qmax(LCHILD, l, r));
    if(r > mid)rtn = max(rtn, qmax(RCHILD, l, r));
    return rtn;
}
int qmin(int cur, int l, int r) //区间最小值
{
    int mid = (LEFT + RIGHT) >> 1, rtn = INF;
    if(LEFT >= l && RIGHT <= r)
        return MIN;
    pushdown2(cur);
    if(l <= mid)rtn = min(rtn, qmin(LCHILD, l, r));
    if(r > mid)rtn = min(rtn, qmin(RCHILD, l, r));
    return rtn;
}
int main()
{
    int i, j, l, r;
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    scanf("%d%d%d", &n, &m, &q);
    build(1, 1, n);
    for(i = 1; i <= n; i++)
    {
        scanf("%d", &j);
        modify(1, i, j);
    }
    while(m--)
    {
        scanf("%d%d%d", &l, &r, &i);
        set(1, l, r, i);
    }
    while(q--)
    {
        scanf("%d%d", &l, &r);
        printf("%d %d %d\n", qsum(1, l, r), qmax(1, l, r), qmin(1, l, r));
    }
    return 0;
}

评论

osu
前排跪Orz
cyxhahaha
前排跪,明明psx的模板。。。
zxozxo
前排跪Orz
tgopknight
妈呀!/Orz
yyh5900
妈呀!/Orz
Little_U
为啥区间加的时候不先pushdown2@zmhx2

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。