有关线段树的一些题目

接近一个星期的学习,蒟蒻总算入门线段树了,贴几类常见线段树题目的代码。如有错误,希望大佬指出。

hdu 1166 敌兵布阵 题目链接

单点更新求区间和

Sample Input

1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End

Sample Output

Case 1:
6
33
59
AC代码

#include <iostream>
#include <cstring>
using namespace std;
int a[50005];
int c[50005];
inline int lowbit(int k)
{
    return k & (-k);
}
inline void update(int k, int x)
{
    while (k <= 50005)
    {
        c[k] += x;
        k += lowbit(k);
    }
}
inline int getsum(int k)
{
    int ans = 0;
    while (k > 0)
    {
        ans += c[k];
        k -= lowbit(k);
    }
    return ans;
}
int main()
{
    char s[10];
    int t;
    scanf("%d", &t);
    for (int l = 1; l <= t; l++)
    {
        memset(c, 0, sizeof c);
        int n, q, w;
        scanf("%d", &n);
        printf("Case %d:\n", l);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for (int i = 1; i <= n; i++)
        {
            for (int j = i - lowbit(i) + 1; j <= i; j++)
                c[i] += a[j];
        }
        while (true)
        {
            scanf("%s", s);
            if (s[0] == 'E')
                break;
            scanf("%d%d", &q, &w);
            if (s[0] == 'A')
                update(q, w);
            else if (s[0] == 'S')
                update(q, -w);
            else
                printf("%d\n", getsum(w) - getsum(q - 1));
        }
    }
}

hdu 1754 I Hate It 题目链接

单点更新求区间最大值

Sample Input

5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5

Sample Output

5
6
5
9
AC代码

#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
    int left;//对应数组a
    int right;//对应数组a
    int maxx;
    int mark;//懒惰标记
};
//k对应结构体que
int n, ql, qr, id, val;
int a[200005];
node que[4 * 200005];
//更新最值
void push_up(int k)
{
    que[k].maxx = max(que[k << 1].maxx, que[k << 1 | 1].maxx);
}
//传递标记
void push_down(int k)
{
    if (que[k].mark != 0)
    {
        int temp = que[k].mark;
        que[k].mark = 0;
        que[k << 1].mark += temp;
        que[k << 1 | 1].mark += temp;
        que[k << 1].maxx += temp;
        que[k << 1 | 1].maxx += temp;
    }
}
//建树
void build(int left, int right, int k)
{
    que[k].left = left;
    que[k].right = right;
    que[k].mark = 0;
    que[k].maxx = 0;
    if (left == right)
    {
        que[k].maxx = a[left];
        return;
    }
    int mid = (left + right) >> 1;
    build(left, mid, k << 1);
    build(mid + 1, right, k << 1 | 1);
    push_up(k);//向上更新最大值
}
//询问最大值
int querymax(int left, int right, int k)
{
    if (ql <= left && right <= qr)
        return que[k].maxx;
    if (right < ql || qr < left)//区间没有交集
        return 0;
    push_down(k);//向下传递标记
    int mid = (left + right) >> 1;
    return max(querymax(left, mid, k << 1), querymax(mid + 1, right, k << 1 | 1));
}
void onepoint_update(int left, int right, int k)
{
    if (left == right && left == id)
    {
        que[k].maxx = val;
        return;
    }
    int mid = (left + right) >> 1;
    if (id <= mid)
        onepoint_update(left, mid, k << 1);
    else
        onepoint_update(mid + 1, right, k << 1 | 1);
    push_up(k);//向上更新最大值
}
void update(int left, int right, int k)
{
    if (right < ql || qr < left)
        return;
    if (ql <= left && right <= qr)
    {
        que[k].mark += val;
        que[k].maxx += val;
        return;
    }
    push_down(k);//向下传递标记
    int mid = (left + right) >> 1;
    update(left, mid, k << 1);
    update(mid + 1, right, k << 1 | 1);
    push_up(k);//向上更新最大值
}
int main()
{
    int n, m;
    char op[2];
    while (scanf("%d%d", &n, &m) > 0)
    {
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        build(1, n, 1);
        while (m--)
        {
            scanf("%s", op);
            if (op[0] == 'Q')
            {
                scanf("%d%d", &ql, &qr);
                printf("%d\n", querymax(1, n, 1));
            }
            else
            {
                scanf("%d%d", &id, &val);
                onepoint_update(1, n, 1);
            }
        }
    }
}

poj 3468 A Simple Problem with Integers 题目链接

区间更新 区间求和

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15
AC代码

#include <cstdio>
#include <algorithm>
#define ll long long
struct node
{
	int l;
	int r;
	ll sum;
	ll mark;
}que[100005 * 4];
ll val;
int ql, qr;
void push_up(int k)
{
	que[k].sum = que[k << 1].sum + que[k << 1 | 1].sum;
}
void push_down(int k)
{
	if (que[k].mark)
	{
		ll temp = que[k].mark;
		que[k].mark = 0;
		que[k << 1].mark += temp;
		que[k << 1 | 1].mark += temp;
		que[k << 1].sum += temp * (que[k << 1].r - que[k << 1].l + 1);
		que[k << 1 | 1].sum += temp * (que[k << 1 | 1].r - que[k << 1 | 1].l + 1);
	}
}
void build(int left, int right, int k)
{
	que[k].l = left;
	que[k].r = right;
	que[k].mark = 0;
	if (left == right)
	{
		scanf("%lld", &que[k].sum);
		return;
	}
	int mid = (left + right) >> 1;
	build(left, mid, k << 1);
	build(mid + 1, right, k << 1 | 1);
	push_up(k);
}
void update(int left, int right, int k)
{
	if (right < ql || qr < left)
		return;
	if (ql <= left && right <= qr)
	{
		que[k].mark += val;
		que[k].sum += val * (que[k].r - que[k].l + 1);
		return;
	}
	push_down(k);
	int mid = (left + right) >> 1;
	update(left, mid, k << 1);
	update(mid + 1, right, k << 1 | 1);
	push_up(k);
}
ll querysum(int left, int right, int k)
{
	if (right < ql || qr < left)
		return 0;
	if (ql <= left && right <= qr)
		return que[k].sum;
	push_down(k);
	int mid = (left + right) >> 1;
	return querysum(left, mid, k << 1) + querysum(mid + 1, right, k << 1 | 1);
}
int main()
{
	int n, m;
	char op[2];
	scanf("%d%d", &n, &m);
	build(1, n, 1);
	while (m--)
	{
		scanf("%s", op);
		if (op[0] == 'Q')
		{
			scanf("%d%d", &ql, &qr);
			printf("%lld\n", querysum(1, n, 1));
		}
		else
		{
			scanf("%d%d%lld", &ql, &qr, &val);
			update(1, n, 1);
		}
	}
}

poj 2528 Mayor’s posters 题目链接

区间染色,求最后颜色的数量(这个题目要离散化一下)

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4
AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
using namespace std;
int ql, qr;
ll val;
int book[200005], a[200005];
struct tttt
{
	int a;
	int b;
}temp[200005];
struct node
{
	int l;
	int r;
	ll mark;//用来标记这个区间的值,减少更新次数
}que[200005 * 4];
void push_up(int k)
{
	;//不用向上更新
}
void push_down(int k)
{
	if (que[k].mark)
	{
		que[k << 1].mark = que[k].mark;
		que[k << 1 | 1].mark = que[k].mark;
		que[k].mark = 0;
	}
}
void build(int left, int right, int k)
{
	que[k].l = left;
	que[k].r = right;
	que[k].mark = 0;
	if (left == right)
		return;
	int mid = (left + right) >> 1;
	build(lson);
	build(rson);
}
void update(int left, int right, int k)
{
	if (ql <= left && right <= qr)
	{
		que[k].mark = val;
		return;
	}
	if (right < ql || qr < left)
		return;
	push_down(k);
	int mid = (left + right) >> 1;
	update(lson);
	update(rson);
	push_up(k);
}
/* void update(int left, int right, int k) { if (ql <= left && right <= qr) { que[k].mark = val; return; } push_down(k); int mid = (left + right) / 2; if (ql <= mid) update(lson); if (qr > mid) update(rson); } */
void query(int left, int right, int k)
{
	if (que[k].mark)
	{
		book[que[k].mark] = 1;
		return;
	}
	if (left == right)
		return;
	int mid = (left + right) >> 1;
	query(lson);
	query(rson);
}
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, tot = 0;
		scanf("%d", &n);
		memset(book, 0, sizeof book);
		for (int i = 0; i < n; i++)
		{
			scanf("%d%d", &temp[i].a, &temp[i].b);
			a[tot++] = temp[i].a;
			a[tot++] = temp[i].b;
		}
		sort(a, a + tot);
		for (int i = 0; i < n; i++)
		{
			temp[i].a = lower_bound(a, a + tot, temp[i].a) - a + 1;
			temp[i].b = lower_bound(a, a + tot, temp[i].b) - a + 1;
		}
		build(1, tot, 1);
		for (int i = 0; i < n; i++)
		{
			ql = temp[i].a;
			qr = temp[i].b;
			val = i + 1;
			update(1, tot, 1);
		}
		ql = 1; qr = tot;
		query(1, tot, 1);
		ll ans = 0;
		for (int i = 0; i < tot; i++)
			if (book[i])
				ans++;
		printf("%lld\n", ans);
	}
}

hdu 1698 Just a Hook 题目链接

区间更新为定值,区间求和

Sample Input

1
10
2
1 5 2
5 9 3

Sample Output

Case 1: The total value of the hook is 24.
AC代码

#include <iostream>
#define ll long long
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
using namespace std;
int ql, qr;
ll val;
struct node
{
    int l;
    int r;
    ll sum;
    ll mark;
}que[200005 * 4];
void push_up(int k)
{
    que[k].sum = que[k << 1].sum + que[k << 1 | 1].sum;
}
void push_down(int k)
{
    if (que[k].mark)
    {
        ll t = que[k].mark;
        que[k].mark = 0;
        que[k << 1].sum = t * (que[k << 1].r - que[k << 1].l + 1);
        que[k << 1 | 1].sum = t * (que[k << 1 | 1].r - que[k << 1 | 1].l + 1);
        que[k << 1].mark = t;
        que[k << 1 | 1].mark = t;
    }
}
void build(int left, int right, int k)
{
    que[k].l = left;
    que[k].r = right;
    que[k].mark = 0;
    if (left == right)
    {
        que[k].sum = 1;
        return;
    }
    int mid = (left + right) >> 1;
    build(lson);
    build(rson);
    push_up(k);
}
void update(int left, int right, int k)
{
    if (right < ql || qr < left)
        return;
    if (ql <= left && right <= qr)
    {
        que[k].sum = val * (right - left + 1);
        que[k].mark = val;
        return;
    }
    push_down(k);
    int mid = (left + right) >> 1;
    update(lson);
    update(rson);
    push_up(k);
}
ll querysum(int left, int right, int k)
{
    if (right < ql || qr < left)
        return 0;
    if (ql <= left && right <= qr)
        return que[k].sum;
    push_down(k);
    int mid = (left + right) >> 1;
    return querysum(lson) + querysum(rson);
}
int main()
{
    int t, l = 1;
    scanf("%d", &t);
    while (t--)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        build(1, n, 1);
        while (m--)
        {
            scanf("%d%d%lld", &ql, &qr, &val);
            update(1, n, 1);
        }
        ql = 1;
        qr = n;
        printf("Case %d: The total value of the hook is %lld.\n", l++, querysum(1, n, 1));
    }
}

poj 2777 Count Color 题目链接

区间更新,区间计算数量,加了一点状压思想

Sample Input

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

Sample Output

2
1
AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
int ql, qr, val;
struct node
{
	int l;
	int r;
	int mark;
	int sum;
}que[100005 * 4];
void push_up(int k)
{
	que[k].sum = que[k << 1].sum | que[k << 1 | 1].sum;
}
void push_down(int k)
{
	if (que[k].mark)
	{
		int t = que[k].mark;
		que[k].mark = 0;
		que[k << 1].mark = t;
		que[k << 1 | 1].mark = t;
		que[k << 1].sum = t;
		que[k << 1 | 1].sum = t;
	}
}
void build(int left, int right, int k)
{
	que[k].l = left;
	que[k].r = right;
	que[k].mark = 0;
	if (left == right)
	{
		que[k].sum = 1;
		return;
	}
	int mid = (left + right) >> 1;
	build(left, mid, k << 1);
	build(mid + 1, right, k << 1 | 1);
	push_up(k);
}
void update(int left, int right, int k)
{
	if (right < ql || qr < left)
		return;
	if (ql <= left && right <= qr)
	{
		que[k].mark = 1 << (val - 1);
		que[k].sum = 1 << (val - 1);
		return;
	}
	push_down(k);
	int mid = (left + right) >> 1;
	update(left, mid, k << 1);
	update(mid + 1, right, k << 1 | 1);
	push_up(k);
}
int query(int left, int right, int k)
{
	if (right < ql || qr < left)
		return 0;
	if (ql <= left && right <= qr)
		return que[k].sum;
	push_down(k);
	int mid = (left + right) >> 1;
	return query(left, mid, k << 1) | query(mid + 1, right, k << 1 | 1);
}
int main()
{
	int n, q;
	char op[2];
	while (scanf("%d%*d%d", &n, &q) > 0)
	{
		build(1, n, 1);
		while (q--)
		{
			scanf("%s", op);
			if (op[0] == 'C')
			{
				scanf("%d%d%d", &ql, &qr, &val);
				update(1, n, 1);
			}
			else
			{
				scanf("%d%d", &ql, &qr);
				if (ql > qr)
				{
					ql ^= qr;
					qr ^= ql;
					ql ^= qr;
				}
				int ans = query(1, n, 1);
				int cnt = 0;
				while (ans)
				{
					if (ans & 1)
						cnt++;
					ans >>= 1;
				}
				printf("%d\n", cnt);
			}
		}
	}
}
全部评论

相关推荐

11-29 11:21
门头沟学院 Java
总包48.5w,意想不到的价格
想开了的垂耳兔很喜欢拱白菜:转人工
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务