線段樹之Find the minimum

Find the minimum

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 90  Solved: 22
[Submit][Status][Web Board]

Description

Given an integer array of size N, we define two kind of operators:
1. Add(L,R,W) : adding an integer W to every element in subarray[L,R];
2. Min(L,R) : returning the minimum number in subarray[L,R].
Note. L and R are the index of array starting from 0. L > R is possible. If L > R, the subarray is composed of array[L], array[L+1].....array[N-1], array[0], array[1],.....array[R].

Input

There are several test cases, processed to the end of file.
For each test, the first line contains two positive integers N and M. N is the size of array, and M is the number of the operation. 
The second line contains N array elements, a1, a2, a3, ...., and an.
Then in the following M lines, each line contains an operation. If the line contains three integers L,R and W, it means the add(L,R,W) operator should be involved. If the line contains two integers L,R , it means the Min(L,R) operator should be involved.
(0<N, M<100,000; 0<= ai <= 10^6; 0 <= L, R <= N – 1, -10^6 <= W <= 10^6。)

Output

 For each Min(L,R) operator in test case, output the return value.

Sample Input

3 3
1 2 4
0 2
0 0 1
0 2

Sample Output

1
2

題意:

         給你一個不超過100000的數組,每個元素的和在1~10^6之間,現在又兩種操作:給你三個數L  R  W,或者兩個數L R
,前者是在L~R的區間內每個數都加W,後者是在L~R的區間內求最小的值,L和R的大小關係不固定。

感悟:

         第一次在地大碰到這題的時候,當時以爲很容易,就用了數組,結果就一直超時,連輸入輸出都給它優化了,還是沒什麼進展,後來才知道要用線段樹。

代碼:

#include<iostream>
#include<cstdio>
//#define MIN(a,b) (a>b?b:a) 用這個會出現*Accepted-24924,( 百度了一下,沒度出來,不知道是什麼玩意兒)
using namespace std;

struct node{
    int left,right,mid,x,add;
}tree[400010];

int n,m,L,R,w,a[1000010];

long long MIN(long long a,long long b)//這個就可以直接過了
{
    return a > b?b:a;
}

void build(int le,int ri,int num)//構建一個線段樹
{
    tree[num].left= le;
    tree[num].right = ri;
    tree[num].add = 0;
    tree[num].mid = (le + ri) /2;
    if(le!=ri)
    {
        build(le,tree[num].mid,num*2);
        build(tree[num].mid+1,ri,num*2+1);
        tree[num].x=MIN(tree[num*2].x,tree[num*2+1].x);
    }
    else
    {
        tree[num].x=a[le];
        return ;
    }
}

void change(int le,int ri,int num,int cha)
{
    if(tree[num].left==le&&tree[num].right==ri)
    {
        tree[num].add += cha;
        return ;
    }
    if(tree[num].add)
    {
        tree[num*2].add+=tree[num].add;//將加的數傳下去
        tree[num*2+1].add += tree[num].add;
        tree[num].add=0;
    }
    if(ri<=tree[num].mid)//這裏被坑過,必須是<=,避免出現tree[num].mid+1比ri大的情況,不然會出現Runtime Error 
        change(le,ri,num*2,cha);
    else if(le>tree[num].mid)
        change(le,ri,num*2+1,cha);
    else
    {
        change(le,tree[num].mid,num*2,cha);
        change(tree[num].mid+1,ri,num*2+1,cha);
    }
    tree[num].x=MIN(tree[num*2].x+tree[num*2].add,tree[num*2+1].x+tree[num*2+1].add);
//    printf("%d %d\n",num,tree[num].x);
}

int findMIN(int le,int ri,int num)
{
    int ls,rs;
    if(tree[num].left==le&&tree[num].right==ri)
        return tree[num].x+tree[num].add;
    ls=num*2;rs=num*2+1;
    if(tree[num].add)
    {
        tree[num].x += tree[num].add;
        tree[ls].add += tree[num].add;
        tree[rs].add += tree[num].add;
        tree[num].add = 0;
    }
//    printf("%d %d\n",num,tree[num].x);
    if(le>tree[num].mid)
        return findMIN(le,ri,rs);
    else if(ri<=tree[num].mid)
        return findMIN(le,ri,ls);
    else
    {
        return MIN(findMIN(le,tree[num].mid,ls),findMIN(tree[num].mid+1,ri,rs));
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        int i;char z;
        for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
        build(1,n,1);
        for(i=0;i<m;i++)
        {
            scanf("%d %d%c",&L,&R,&z);
            L++;R++;
            if(z=='\n')
            {
                if(L<=R)
                printf("%d\n",findMIN(L,R,1));
                else
                    printf("%d\n",MIN(findMIN(L,n,1),findMIN(1,R,1)));
            }

            else
            {
                scanf("%d",&w);
                if(L<=R)
                change(L,R,1,w);
                else
                {
                    change(L,n,1,w);
                    change(1,R,1,w);
                }
            }
        }
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章