线段树之Find the minimum

来源:互联网 发布:大数据产业园发展模式 编辑:程序博客网 时间:2024/05/29 03:13

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;}