解題思路:
建立主席樹對於第i顆線段樹來說,區間(l,r)表示左端點是l-r的點,右端點是i的區間情況,對此第i顆線段樹由i-1顆轉移過來時只需要對當前線段樹進行(1,i)區間都加上a[i]的值,那麼這個操作就可以做區間更新,之後就是維護線段樹區間最大值和位置就ok了.
然後先把i個最大值插入優先佇列,i個最大值分別為第i個線段樹的可選擇的區間長度大小,即(i-r+1,i-l+1)中的最大值,假設在此區間中的最大值位置在m,取出之後將區間**為(i-r+1,m-1)和(m+1,i-l+1),對這兩個區間還是可以用線段樹求出最大值和位置,然後將這兩個插入佇列中即可,在佇列中取出前k個元素就是前k大的區間和。
#include#define inf 0x3f3f3f3f
#define lson l,mid
#define rson mid+1,r
using namespace std;
typedef long long ll;
const int mx = 5e5 + 10;
const int mod = 1e9+7;
int n,m,l1,r1,root[mx];
int a[mx],add[mx*30],rs[mx*30];
int siz,ls[mx*30],d;
struct node
};struct data
s[mx*30];
priority_queue st;
void build(int& rt,int l,int r)
int mid = (l+r)>>1;
build(ls[rt],lson);
build(rs[rt],rson);
}data up(data a,data b)
void update(int x,int &y,int l,int r,int l,int r)
int mid = (l+r)>>1;
if(r<=mid) update(ls[x],ls[y],lson,l,r);
else if(l>mid) update(rs[x],rs[y],rson,l,r);
else
s[y] = up(s[ls[y]],s[rs[y]]);
s[y].ma += add[y];
}data query(int rt,int l,int r,int l,int r)
; if(l<=mid) ans = up(ans,query(ls[rt],lson,l,r));
if(r>mid) ans = up(ans,query(rs[rt],rson,l,r));
return data;
}int main()
); }
}ll ans = 0;
data ret;
while(m--));
}if(now.r-now.p>0));} }
printf("%lld\n",ans);
return 0;
}
洛谷P2048 超級鋼琴 堆 主席樹
乙個長度為n n的序列,求m m個長度在 l,r l r 之間的子串行,使得這些子串行的元素之和最大。顯然暴力是很難搞的,考慮先用字首和。那麼我們要求的就是 i 1mm ax s um k su m x 1 x l 1 k x r 1 i 1 m max sum k s um x 1 x l 1 k...
靜態主席樹(區間第k小) 洛谷P3834
時間限制1.00s 1.20s 記憶體限制125.00mb 250.00mb 這是個非常經典的主席樹入門題 靜態區間第k小 資料已經過加強,請使用主席樹。同時請注意常數優化 如題,給定n個整數構成的序列,將對於指定的閉區間查詢其區間內的第k小值。第一行包含兩個正整數n m,分別表示序列的長度和查詢的...
線段樹 單點修改 區間查詢 洛谷P4588
想了半天 這個和線段樹什麼關係!最後發現我就是豬豬 害就是個板子題 把每乙個葉子節點的值賦值為1 如果第m個是1 n 就把m這個點的值變為n 如果是2 n 就把n點的值變為1 include include include include include include include includ...