HDU 1698 Just a Hook(线段树维护区间)

传送门

大概意思就是一开始所有数字为1,然后把一些连续的数字变为一个数,最后求变换完成的数字序列的和。肯定是用线段树做没跑了,然后这个题也是比较简单,建好树之后光维护就行了,不需要查询操作,因为序列最终的和就是树根的值,直接输出就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5+10;
int a[maxn],tree[maxn*4],add[maxn*4];
void Build(int p,int l,int r)
{
    if(l == r)
    {
        tree[p] = 1;
        return;
    }
    int mid = (l + r) / 2;
    Build(p * 2,l,mid);
    Build(p * 2 + 1,mid + 1,r);
    tree[p] = tree[p * 2] + tree[p * 2 + 1];
}
void Push(int p,int l,int r)
{
    if(add[p])
    {
        int mid = (l + r) / 2;
        tree[p * 2] = (mid - l + 1) * add[p];
        tree[p * 2 + 1] = (r - mid) * add[p];
        add[p * 2] = add[p];
        add[p * 2 + 1] = add[p];
        add[p] = 0;
    }
}
void Change(int p,int l,int r,int L,int R,int num)
{
    if(L <= l && R >= r)
    {
        tree[p] = (r - l + 1) * num;
        add[p] = num;
        return;
    }
    Push(p,l,r);
    int mid = (l + r) / 2;
    if(L <= mid)
        Change(p * 2,l,mid,L,R,num);
    if(R > mid)
        Change(p * 2 + 1,mid + 1,r,L,R,num);
    tree[p] = tree[p * 2] + tree[p * 2 + 1];
}
int main()
{
    int t,cas = 0;
    scanf("%d",&t);
    while(t--)
    {
        memset(add,0,sizeof(add));
        int n,q;
        scanf("%d %d",&n,&q);
        Build(1,1,n);
        while(q--)
        {
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            Change(1,1,n,x,y,z);
        }
        printf("Case %d: The total value of the hook is %d.\n",++cas,tree[1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao__hei__hei/article/details/87902871