[洛谷2357] 守墓人
题目描述
在一个荒凉的墓地上
有一个令人尊敬的守墓人, 他看守的墓地从来
没有被盗过, 所以人们很放心的把自己的先人的墓
安顿在他那
守墓人能看好这片墓地是必然而不是偶然.....
因为....守墓人懂风水 0.0
他把墓地分为主要墓碑和次要墓碑, 主要墓碑
只能有 1 个, 守墓人把他记为 1 号, 而次要墓碑有
n-1 个,守墓人将之编号为 2,3...n,所以构成了一个有 n 个墓碑的墓地。
而每个墓碑有一个初始的风水值,这些风水值决定了墓地的风水的好坏,所以守墓人
需要经常来查询这些墓碑。
善于运用风水的守墓人,通过一次次逆天改命,使得自己拥有了无限寿命,没人知道
他活了多久。
这天,你幸运的拜访到了他,他要求你和他共同见证接下来几年他的战果,但不过他
每次统计风水值之和都需要你来帮他计算,算错了他会要你命 QAQ
风水也不是不可变,除非遭遇特殊情况,已知在接下来的 2147483647 年里,会有 n 次
灾难,守墓人会有几个操作:
1.将[l,r]这个区间所有的墓碑的风水值增加 k。
2.将主墓碑的风水值增加 k
3.将主墓碑的风水值减少 k
4.统计[l,r]这个区间所有的墓碑的风水值之和
5.求主墓碑的风水值
上面也说了,很多人会把先人的墓安居在这里,而且守墓人活了很多世纪→_→,墓碑
的数量会多的你不敢相信= =
守墓人和善的邀请你帮他完成这些操作,要不然哪天你的旅馆爆炸了,天上下刀子.....
为了活命,还是帮他吧
输入输出格式
输入格式:第一行,两个正整数 n,f 表示共有 n 块墓碑,并且在接下来的
2147483647 年里,会有 f 次世界末日
第二行,n 个正整数,表示第 i 块墓碑的风水值
接下来 f 行,每行都会有一个针对世界末日的解决方案,如题所述,标记同题
输出格式:输出会有若干行,对 4 和 5 的提问做出回答
输入输出样例
5 7 0 0 0 0 0 1 1 5 1 1 1 3 3 2 3 3 1 4 1 5 2 1 5
16 7
说明
20%的数据满足:1≤n≤100
50%的数据满足:1≤n≤6000
100%的数据满足:1≤n,f≤2*10^5
思路
线段树;
代码实现
1 #include<cstdio> 2 #define LL long long 3 const int maxn=2e5+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]=t[ls]+t[rs]; 17 } 18 void down(int k,int l,int r){ 19 int mid=l+r>>1,ls=k<<1,rs=ls|1; 20 t[ls]+=(mid-l+1)*f[k]; 21 t[rs]+=(r-mid)*f[k]; 22 f[ls]+=f[k]; 23 f[rs]+=f[k]; 24 f[k]=0; 25 } 26 void change(int k,int l,int r,int al,int ar,LL x){ 27 if(l==al&&r==ar){ 28 t[k]+=(r-l+1)*x; 29 f[k]+=x; 30 return; 31 } 32 int mid=l+r>>1,ls=k<<1,rs=ls|1; 33 if(f[k]) down(k,l,r); 34 if(al<=mid) change(ls,l,mid,al,min_(ar,mid),x); 35 if(ar>mid) change(rs,mid+1,r,max_(al,mid+1),ar,x); 36 t[k]=t[ls]+t[rs]; 37 } 38 LL query(int k,int l,int r,int al,int ar){ 39 if(l==al&&r==ar) return t[k]; 40 int mid=l+r>>1,ls=k<<1,rs=ls|1; 41 LL ret=0; 42 if(f[k]) down(k,l,r); 43 if(al<=mid) ret+=query(ls,l,mid,al,min_(ar,mid)); 44 if(ar>mid) ret+=query(rs,mid+1,r,max_(al,mid+1),ar); 45 return ret; 46 } 47 int opt,l,r; 48 LL k; 49 int main(){ 50 scanf("%d%d",&n,&m); 51 build(1,1,n); 52 while(m--){ 53 scanf("%d",&opt); 54 if(opt==1){ 55 scanf("%d%d%lld",&l,&r,&k); 56 change(1,1,n,l,r,k); 57 } 58 if(opt==2){ 59 scanf("%lld",&k); 60 change(1,1,n,1,1,k); 61 } 62 if(opt==3){ 63 scanf("%lld",&k); 64 change(1,1,n,1,1,-k); 65 } 66 if(opt==4){ 67 scanf("%d%d",&l,&r); 68 printf("%lld\n",query(1,1,n,l,r)); 69 } 70 if(opt==5) printf("%lld\n",query(1,1,n,1,1)); 71 } 72 return 0; 73 }