vijos p1659——河蟹王国(线段树)(复习)
描述
河蟹王國有一位河蟹國王,他的名字叫羊駝。河蟹王國富饒安定,人們和諧相處。有一天,羊駝國王心血來潮,想在一部分人中挑出最和諧的人。于是,羊駝國王將他的子民排成了一列(==!!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范圍內。
?
區間更改,區間查詢——線段樹/樹狀數組
這里用的線段樹,注意結構體中還要有一個add,表示增加量。在更新操作中,注意:當查詢到區間匹配時,區間最大值直接加上輸入的增量,用add傳遞下去再pushup。傳遞add就pushdown。一定要深刻理解up和down的用法。
居然沒有區間和,總覺得寫起來怪怪的。。。
還發現了一個很詭異的東西,當查詢寫成int函數時,不會超時。但當寫成void函數時要超時4組,加上inline后才不會超時。。。
祝自己NOIP順利~
?
#include<bits/stdc++.h> using namespace std; #define L(u) (u*2) #define R(u) (u*2+1) const int maxn=1000005; int a[maxn]; struct node{int l,r,maxnum,add; }w[maxn]; int n,m;int ans=0; inline void pushup(int u) {w[u].maxnum=max(w[L(u)].maxnum,w[R(u)].maxnum);return ; } inline void pushdown(int u) {w[L(u)].add+=w[u].add;w[L(u)].maxnum+=w[u].add;w[R(u)].add+=w[u].add;w[R(u)].maxnum+=w[u].add;w[u].add=0;return ; } inline void buildtree(int u,int left,int right) {w[u].l=left;w[u].r=right;if(left==right){w[u].maxnum=a[left];return ;}int mid=(left+right)>>1;buildtree(L(u),left,mid);buildtree(R(u),mid+1,right);pushup(u); } inline void findans(int u,int left,int right) {if(w[u].l==left&&w[u].r==right){ans=max(ans,w[u].maxnum);return ;}if(w[u].add!=0)pushdown(u);int mid=(w[u].l+w[u].r)>>1;if(left>=mid+1)findans(R(u),left,right);else if(right<=mid)findans(L(u),left,right);else{findans(L(u),left,mid);findans(R(u),mid+1,right);}return ; } inline void update(int u,int left,int right,int val) {if(w[u].l==left&&w[u].r==right){w[u].maxnum+=val;w[u].add+=val;return ;}if(w[u].add!=0)pushdown(u);int mid=(w[u].l+w[u].r)>>1;if(left>=mid+1)update(R(u),left,right,val);else if(right<=mid)update(L(u),left,right,val);else{update(L(u),left,mid,val);update(R(u),mid+1,right,val);}pushup(u); } int main() {scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);buildtree(1,1,n);scanf("%d",&m);for(int i=1;i<=m;i++){int q;scanf("%d",&q);if(q==1){int x,y,z;scanf("%d%d%d",&x,&y,&z);update(1,x,y,z);continue;}else{int x,y;scanf("%d%d",&x,&y);ans=-100000000;findans(1,x,y);printf("%d\n",ans);continue;}}return 0; }?
轉載于:https://www.cnblogs.com/937337156Zhang/p/6071445.html
總結
以上是生活随笔為你收集整理的vijos p1659——河蟹王国(线段树)(复习)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS-改变UITextField的Pl
- 下一篇: BootStrap_01之全局样式