C - Just a Hook HDU - 1698+ E - A Simple Problem with Integers POJ - 3468(lazy标记+线段树)

版权声明:莉莉莉 https://blog.csdn.net/qq_41700151/article/details/81368602

首先,lazy标记是什么呢?

比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,它的节点标记为rt,这时tree[rt].l== a && tree[rt].r == b 这时我们可以一步更新此时rt节点的sum[rt]的值,sum[rt] += c* (tree[rt].r - tree[rt].l + 1),注意关键的时刻来了,如果此时按照常规的线段树的update操作,这时候还应该更新rt子节点的sum[]值,而Lazy思想恰恰是暂时不更新rt子节点的sum[]值,到此就return,直到下次需要用到rt子节点的值的时候才去更新,这样避免许多可能无用的操作,从而节省时间。
lazy标记用到的代码

m=node[i].r-node[i].l+1        //代表区间长度
void push_down(int i,int m)  
{
    if(add[i]!=0)
    {
        add[i<<1]=add[i];      //把i的标记压给他的下一层的左区间
        add[i<<1|1]=add[i];    //把i的标记压给他的下一层的右区间
        node[i<<1].value=add[i]*(m-(m>>1));  
        //m>>1是上一层区间的一半的长度
        node[i<<1|1].value=add[i]*(m>>1);  
        //是另一半的长度
        add[i]=0;
    }
}

题目

C - Just a Hook HDU - 1698
Now Pudge wants to do some operations on the hook.
Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks.
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows:
For each cupreous stick, the value is 1.
For each silver stick, the value is 2.
For each golden stick, the value is 3.
Pudge wants to know the total value of the hook after performing the operations.
You may consider the original hook is made up of cupreous sticks.
Input
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations.
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind.
Output
For each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example.
Sample Input

1
10
2
1 5 2
5 9 3

Sample Output

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

题意:
有t组测试样例,每组里有n个小木棍,他的价值为1,然后进行m次操作,把第i个到第j个小木棍变成价值为2或者3的小棍,然后问你换完以后的总价值。

思路:
线段树加lazy标记,但是这个题更新操作时不能是加,应该是直接赋成那个新的值。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,i<<1
#define rson m+1,r,i<<1|1
const int MAXX=2e5+5;
int ans;
struct Node{
   int l,r,value;
   int mid()
   {
       return (l+r)/2.0;
   }
};
Node node[MAXX<<2];   //定义数据量的4倍大小

int add[MAXX<<2];    //lazy标记数组
void push_up(int i)
{
    node[i].value=node[i<<1].value+node[i<<1|1].value;
    //求他的左儿子和右儿子的和
}

void push_down(int i,int m)  //lazy标记
{
    if(add[i]!=0)
    {
        add[i<<1]=add[i];
        add[i<<1|1]=add[i];
        node[i<<1].value=add[i]*(m-(m>>1));
        node[i<<1|1].value=add[i]*(m>>1);
        add[i]=0;
    }
}

void Build(int l,int r,int i)   //模拟建树过程
{
    node[i].l=l;
    node[i].r=r;
    node[i].value=0;
    if(l==r)
    {
        node[i].value=1;
        return ;
    }
    int m=node[i].mid();
    Build(lson);
    Build(rson);
    push_up(i);
}

void update(int i,int aa,int bb,int cc) //aa是起始区间,bb是终止区间
{
    if(node[i].l==aa&&node[i].r==bb)    
    //node里存的是树的区间,(aa,bb)是要找的区间,找到对应的区间
    {
        add[i]=cc;
        node[i].value=(bb-aa+1)*cc;
        return ;
    }
    push_down(i,node[i].r-node[i].l+1);
    int m=node[i].mid();
    if(bb<=m)    //要找的区间在中值的左边
        update(i<<1,aa,bb,cc);
    else if(aa>m)    //在中值的右边
        update(i<<1|1,aa,bb,cc);
    else     //在中值的两边
    {
        update(i<<1,aa,m,cc);
        update(i<<1|1,m+1,bb,cc);
    }
    push_up(i);
}

//void query(int l,int r,int i)
//{
//    if(node[i].l==l&&node[i].r==r)
//    {
//         ans+=node[i].value;
//         return ;
//    }
//    push_down(i,node[i].r-node[i].l+1);
//    int m=node[i].mid();
//    if(r<=m)
//        query(l,r,i<<1);
//    else
//    {
//        if(l>m)
//            query(l,r,i<<1|1);
//        else
//        {
//            query(lson);
//            query(rson);
//        }
//    }
//
//}
int main()
{
    int t,d=1;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        int n;
        memset(add,0,sizeof(add));
        scanf("%d",&n);
        Build(1,n,1);
        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int aa,bb,cc;
            scanf("%d%d%d",&aa,&bb,&cc);
            update(1,aa,bb,cc);
        }
      //  query(1,n,1);
        printf("Case %d: The total value of the hook is %d.\n",d++,node[1].value);
    }


    return 0;

}


E - A Simple Problem with Integers POJ - 3468
You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+1, … , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
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

Hint
The sums may exceed the range of 32-bit integers.
Code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<set>
#include<map>
using namespace std;
#define ll long long

const int MAXX=100000+50;
ll ans;
struct Node
{
    int l,r;
   // ll value;
    int mid()
    {
        return (l+r)/2.0;
    }
};
Node node[MAXX<<2];   //定义数据量的4倍大小
ll sum[MAXX<<2];
ll add[MAXX<<2];    //lazy标记数组
void push_up(int i)
{
    sum[i]=sum[i<<1]+sum[i<<1|1];
    //求他的左儿子和右儿子的和
}

void push_down(int i,int m)  //lazy标记
{
    if(add[i]!=0)
    {
        add[i<<1]+=add[i];
        add[i<<1|1]+=add[i];
        sum[i<<1]+=add[i]*(m-(m>>1));
        sum[i<<1|1]+=add[i]*(m>>1);
        add[i]=0;
    }
}

void Build(int l,int r,int i)   //模拟建树过程
{
    node[i].l=l;
    node[i].r=r;
    sum[i]=0;
    if(l==r)
    {
        scanf("%lld",&sum[i]);
        return ;
    }
    int m=node[i].mid();
    Build(l,m,i<<1);
    Build(m+1,r,i<<1|1);
    push_up(i);
}

void update(int i,int aa,int bb,int cc) //aa是起始区间,bb是终止区间
{
    if(node[i].l==aa&&node[i].r==bb)
    {
        add[i]+=cc;
        sum[i]+=(ll)(bb-aa+1)*cc;
        return ;
    }
    push_down(i,node[i].r-node[i].l+1);
    int m=node[i].mid();
    if(bb<=m)    //要找的区间在中值的左边
        update(i<<1,aa,bb,cc);
    else if(aa>m)    //在中值的右边
        update(i<<1|1,aa,bb,cc);
    else     //在中值的两边
    {
        update(i<<1,aa,m,cc);
        update(i<<1|1,m+1,bb,cc);
    }
    push_up(i);
}

void query(int bb,int cc,int i)
{
    if(node[i].l==bb&&node[i].r==cc)
    {
         ans+=sum[i];
         return ;
    }
    push_down(i,node[i].r-node[i].l+1);
    int m=node[i].mid();
    if(cc<=m)
        query(bb,cc,i<<1);
    else
    {
        if(bb>m)
            query(bb,cc,i<<1|1);
        else
        {
            query(bb,m,i<<1);
            query(m+1,cc,i<<1|1);
        }
    }

}
int main()
{


    ans=0;
    int m,n;
    memset(add,0,sizeof(add));
    scanf("%d%d",&n,&m);
    Build(1,n,1);

    char aa[3];
    for(int i=0; i<m; i++)
    {
        int bb,cc,dd;
        scanf("%s",aa);
        if(aa[0]=='Q')
        {
            ans=0;
            scanf("%d%d",&bb,&cc);
            query(bb,cc,1);
            printf("%lld\n",ans);
        }
        if(aa[0]=='C')
        {
            scanf("%d%d%d",&bb,&cc,&dd);
            update(1,bb,cc,dd);
        }


    }
    //  query(1,n,1);



    return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_41700151/article/details/81368602