[Vijos] 河蟹王国

描述

河蟹王国有一位河蟹国王,他的名字叫羊驼。河蟹王国富饶安定,人们和谐相处。有一天,羊驼国王心血来潮,想在一部分人中挑出最和谐的人。于是,羊驼国王将他的子民排成了一列(==!!b汗~好长呀)。每个人都有一个初始的和谐值。羊驼国王每次会选择一个区间[L,R],这个区间中和谐值最大的人就是国王选出的人。而且,在某一时间,区间[L',R']里的人会变得熟悉,因此他们每个人的和谐值都会上升一个相同的值C。羊驼国王想知道,对于每一次选择,他选出的最大和谐值是多少。

格式

输入格式

第一行是一个数N(1<=N<=100000),表示人数。

接下来的N行,每行一个数,表示排成的序列第i个人和谐值的初始值。

接下来是一个数M(1<=M<=100000),表示羊驼国王或他的子民有所活动(羊驼国王选择一个区间算一次,某区间里的人增长和谐值算一次)的总次数。

接下来的M行,每行第一个是一个数K,K是1或2,若K=1,接下来有三个数L,R,C,表示区间[L,R]的所有人增加C的和谐值;若K=2,接下来有两个数L,R,表示国王选择了区间[L,R]。

输出格式

每次对于国王选择区间,输出选择区间里的最大和谐值。

样例1

样例输入1

5
1
2
3
4
5
3
2 1 4
1 1 3 3
2 3 5

样例输出1

4
6

限制

每个测试点1s。

提示

保证所有的数以及结果都在longint范围内。

来源

经典问题改编。

思路

。。。带标记下放的区间最大值,然后sb的我交了,,,4边QUQ

代码实现

 1 #include<cstdio>
 2 #define LL long long
 3 const int maxn=1e5+10;
 4 inline LL min_(LL x,LL y){return x<y?x:y;}
 5 inline LL max_(LL x,LL y){return x>y?x:y;}
 6 int n,m;
 7 LL t[maxn<<2],f[maxn<<2];
 8 void build(int k,int l,int r){
 9     if(l==r){
10         scanf("%lld",&t[k]);
11         return;
12     }
13     int mid=l+r>>1,ls=k<<1,rs=ls|1;
14     build(ls,l,mid);
15     build(rs,mid+1,r);
16     t[k]=max_(t[ls],t[rs]);
17 }
18 void f_down(int k,int ls,int rs){
19     t[ls]+=f[k],f[ls]+=f[k];
20     t[rs]+=f[k],f[rs]+=f[k];
21     f[k]=0;
22 }
23 void add(int k,int l,int r,int al,int ar,LL p){
24     if(al <= l && r <= ar){
25         t[k]+=p,f[k]+=p;
26         return;
27     }
28     int mid=l+r>>1,ls=k<<1,rs=ls|1;
29     if(f[k]) f_down(k,ls,rs);
30     if(al<=mid) add(ls,l,mid,al,min_(ar,mid),p);
31     if(ar>mid) add(rs,mid+1,r,max_(al,mid+1),ar,p);
32     t[k]=max_(t[ls],t[rs]);
33 }
34 #define INF 8e18
35 LL big(int k,int l,int r,int al,int ar){
36     if(l==al&&r==ar) return t[k];
37     int mid=l+r>>1,ls=k<<1,rs=ls|1;
38     if(f[k]) f_down(k,ls,rs);
39     LL ret=-INF;
40     if(al<=mid) ret=max_(ret,big(ls,l,mid,al,min_(ar,mid)));
41     if(ar>mid) ret=max_(ret,big(rs,mid+1,r,max_(al,mid+1),ar));
42     return ret;
43 }
44 int main(){
45     scanf("%d",&n);
46     build(1,1,n);
47     scanf("%d",&m);
48     LL c;
49     int k,l,r;
50     for(int i=1;i<=m;i++){
51         scanf("%d",&k);
52         if(k==1){
53             scanf("%d%d%lld",&l,&r,&c);
54             add(1,1,n,l,r,c);
55         }
56         if(k==2){
57             scanf("%d%d",&l,&r);
58             printf("%lld\n",big(1,1,n,l,r));
59         }
60     }
61     return 0;
62 }

 

posted @ 2017-12-15 21:01  J_william  阅读(317)  评论(0编辑  收藏  举报