NOI2010 超級鋼琴

2022-03-03 15:49:50 字數 1419 閱讀 9990

就是我們考慮記錄乙個三元組qwq,乙個是pos,乙個是l,乙個是r。

我們可以用st表來查詢固定左端點,右端點在一段區間內的最大值所在的位置。

然後我們使用優先佇列,不斷累加最大值,然後彈出,求它的區間的子區間內的最大值。

**如下:

#include#include#include#include#include#include#define maxn 500010

using namespace std;

int n,l,r,k,cnt;

long long ans;

int log2[maxn],st[maxn][21],sum[maxn],a[maxn];

struct node

};priority_queueq;

inline void init()

}}inline int query(int l,int r)

inline void solve()

); // printf("%d %d %d %d\n",i,ll,rr,q.top().maxpos);

}while(!q.empty()&&cnt=u.l) q.push((node));

if(u.maxpos+1<=u.r) q.push((node));

}printf("%lld\n",ans);

}int main()

也是維護乙個三元組。

因為求的是乙個連續的區間和,所以我們可以先做一下字首和,然後固定右端點,在可選區間中選擇最小的即可。

就是記錄一下在這個pos為右端點的區間中,已經取到了第多少qwq

維護取第k大就是乙個靜態區間求第k的主席樹經典應用qwq

然後放進堆裡即可。每次取出最大的,然後放入以這個為右端點,的k+1大值。

記得要先離散化一下qwq,還有一直取到頭(也就是字首和減0)的情況——其實就是離散化的時候往陣列裡面放乙個0即可。

**如下:

#include#include#include#include#include#include#define maxn 500010

using namespace std;

int n,k,l,r,top,tot;

int pre[maxn],rt[maxn],sum[maxn];

long long ans;

struct tt[maxn<<5];

struct node

inline int query(int x,int f,int l,int r,int k)

int main()

); }

while(k--)

printf("%lld\n",ans);

return 0;

}

NOI2010 超級鋼琴

傳送門 這個題有趣。巧妙地利用st表和堆 首先最暴力的我就不說了 第二個暴力就是主席樹 堆,預計得分70 80,時間o klog 2n std是用堆儲存可能的區間,然後用st表查詢區間最小值 因為其實如果知道區間右端點,再處理個字首和s 那麼就只要查詢區間最小值就可以了,可以st表o 1 做 inc...

NOI2010 超級鋼琴

求出字首和 對於每個結尾i,設現在取的區間是 j 1,i 則i r j i l,取出該區間sum j 的最小值,將sum i sum j 放入堆中 建立乙個大根堆,每次取出堆頂元素,將排名k 1,將sum i 區間第k小值放入堆中 求區間第k小可以用主席樹 直到取滿k次為止 include incl...

NOI2010 超級鋼琴

和有一道區間前k大異或很像。先求字首和,然後就變成右端點固定,取左端點的第k小問題,主席樹維護即可。並用堆維護前k個。ac pragma gcc optimize ofast funroll all loops include define int long long using namespace...