【Usaco2015 dec 】Counting Haybales

题意

农夫约翰打算重修他的农场。他有 N 块土地,连续排列成一行,标号为 1…N。在每块土地上有任意数量的草堆。他可以发出三种指令:
1) 对一个连续区间的土地,每块土地增加相同数量的草堆。
2) 对一个连续区间的土地,输出其中最少的草堆数量。
3) 对一个连续区间的土地,输出草堆数量总数。

第一行两个正整数,N (1≤N≤200,000) 和 Q (1≤Q≤100,000)。
下一行是N个非负整数,最大100,000,表示每块土地上有多少个草堆。
以下Q行,每行一单个大写字母开头(M,P或S),空格后跟随两个正整数 A 和 B (1≤A≤B≤N), 或者三个正整数 A, B, 和 C (1≤A≤B≤N; 1≤C≤100,000)。当且仅当第一个字母是 P 时,是三个正整数。
当该字母是M,输出区间A…B的最小草堆数。
当该字母是P,在区间A…B,每块土地增加C堆草。
当该字母是M,输出区间A…B的草堆数之和。

每行一个数字,用于响应’M’ 或 ‘S’ 命令。

样例

SAMPLE INPUT:
4 5
3 1 2 4
M 3 4
S 1 3
P 2 3 1
M 3 4
S 1 3
SAMPLE OUTPUT:
2
6
3
8

分析

一道线段树的裸题,维护区间的最小值、和。
没什么好说的,直接套用线段树。
注意用long long

代码

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;
const int inf=2000000001;
const int maxn=200000+20;
const int manq=100000+20;
ll n,q;
struct Tree
{
    ll y1,y2,v;
    ll sumv[maxn*4];
    ll minv[maxn*4];
    ll addv[maxn*4];
    void maintain(ll o,ll L,ll R)
    {
        ll lc=o*2,rc=o*2+1;
        sumv[o]=minv[o]=0;
        if(R>L){
            sumv[o]=sumv[lc]+sumv[rc];
            minv[o]=min(minv[lc],minv[rc]);
        }   
        minv[o]+=addv[o];sumv[o]+=addv[o]*(R-L+1);
    } 
    void update(ll o,ll L,ll R){
        ll lc=o*2;
        ll rc=o*2+1;
        if(y1<=L&&y2>=R)
          addv[o]+=v;
        else{
          ll M=(L+R)>>1;
          if(y1<=M) update(lc,L,M);
          if(y2>M) update(rc,M+1,R);
        }
        maintain(o,L,R);
    }
    ll _min,_sum;
    void query(ll o,ll L,ll R,ll add){
        if(y1<=L&&y2>=R){
            _sum+=sumv[o]+add*(R-L+1);
            _min=min(_min,minv[o]+add);
        }
        else{
            ll M=(R+L)>>1;
            if(y1<=M) query(o*2,L,M,add+addv[o]);
            if(y2>M) query(o*2+1,M+1,R,add+addv[o]);
        }
    }
}t;
int main()
{
    //freopen("haybales.in","r",stdin);
    //freopen("haybales.out","w",stdout);
    cin>>n>>q;
    for(ll i=1;i<=n;i++)
    {
      scanf("%d",&t.v);
      t.y2=t.y1=i;
      t.update(1,1,n);  
    }
    char a[5];
    while(q--)
    {
        scanf("%s",a);
        if(a[0]=='M'){
            t._min=inf;
            scanf("%d%d",&t.y1,&t.y2);
            t.query(1,1,n,0);
            cout<<t._min;
            printf("\n");
        }
        else if(a[0]=='S'){
            t._sum=0;
            scanf("%d%d",&t.y1,&t.y2);
            t.query(1,1,n,0);
            cout<<t._sum;
            printf("\n");
        }
        else if(a[0]=='P'){
            scanf("%d%d%d",&t.y1,&t.y2,&t.v);
            t.update(1,1,n);
        }
    } 
    return 0; 
}

你可能感兴趣的:(线段树,Usaco-2015)