BZOJ 4241: 历史研究——莫队 二叉堆
2017-03-23 16:26
459 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4241
题意:N个int范围内的数,M次询问一个区间最大的(数字*出现次数)(加权众数),可以离线。
似乎正解是分块。。。因为可以离线&&时限大,用莫队算法卡常水过了(捂脸)。
具体方法:先按莫队方法把询问排序,然后考虑转移。
把所有数字离散化,记录每个数的(数字*出现次数),当我们加入/拿走一个数的时候,更新这个值,并维护二叉堆。
复杂度:\(O(N \sqrt N log N)\)
题意:N个int范围内的数,M次询问一个区间最大的(数字*出现次数)(加权众数),可以离线。
似乎正解是分块。。。因为可以离线&&时限大,用莫队算法卡常水过了(捂脸)。
具体方法:先按莫队方法把询问排序,然后考虑转移。
把所有数字离散化,记录每个数的(数字*出现次数),当我们加入/拿走一个数的时候,更新这个值,并维护二叉堆。
复杂度:\(O(N \sqrt N log N)\)
/************************************************************** Problem: 4241 User: will7101 Language: C++ Result: Accepted Time:29968 ms Memory:5984 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=100005; void rd(int &x){ x=0; int ch=getchar(); while(ch<'0'||'9'<ch) ch=getchar(); while('0'<=ch&&ch<='9') x=x*10+ch-'0', ch=getchar(); } int N, M, V, S, be[MAXN], a[MAXN], id[MAXN], di[MAXN], num[MAXN]; ll ans[MAXN], hp[MAXN]; inline void add(int x){ hp[id[x]]+=num[x]; for(int i=id[x], j; i>1; i=j){ j=i>>1; if(hp[i]>hp[j]){ swap(hp[i], hp[j]); swap(id[di[i]], id[di[j]]); swap(di[i], di[j]); }else break; } } inline void del(int x){ hp[id[x]]-=num[x]; for(int i=id[x], j;; i=j){ j=hp[i<<1]>hp[i<<1|1]?i<<1:i<<1|1; if(j>V) break; if(hp[i]<hp[j]){ swap(hp[i], hp[j]); swap(id[di[i]], id[di[j]]); swap(di[i], di[j]); }else break; } } struct Qry{ int l, r, id; bool operator<(const Qry &o)const{ if(be[l]==be[o.l]) return (be[l]&1)?r>o.r:r<o.r; return l<o.l; } }Q[MAXN]; void init(){ sort(num+1, num+N+1); V=unique(num+1, num+N+1)-num-1; for(int i=1; i<=N; ++i) a[i]=lower_bound(num+1, num+V+1, a[i])-num; for(int i=1; i<=V; ++i) id[i]=di[i]=i; } int main(){ rd(N), rd(M); for(int i=1; i<=N; ++i) rd(a[i]), num[i]=a[i]; while(S*S<=M) S++; for(int i=0; i<=N; ++i) be[i]=i/S; init(); for(int i=0; i<M; ++i) rd(Q[i].l), rd(Q[i].r), Q[i].id=i; sort(Q, Q+M); for(int i=0, l=1, r=0; i<M; ++i){ while(r<Q[i].r) add(a[++r]); while(l>Q[i].l) add(a[--l]); while(l<Q[i].l) del(a[l++]); while(r>Q[i].r) del(a[r--]); ans[Q[i].id]=hp[1]; } for(int i=0; i<M; ++i) printf("%lld\n", ans[i]); return 0; }
相关文章推荐
- BZOJ4241 历史研究 (分块 回滚莫队-教程向)
- BZOJ4241 历史研究 莫队算法 堆
- bzoj4241 历史研究 (回滚莫队)
- BZOJ 4241 历史研究 (回滚莫队)
- BZOJ4241 历史研究(莫队)
- [BZOJ]4241 历史研究 回滚莫队
- [bzoj4241]历史研究 回滚莫队
- [BZOJ4241]历史研究(回滚莫队)
- 【BZOJ4241】【回滚莫队】历史研究 (非题解的学习分析)
- [BZOJ4241]-历史研究-回滚莫队
- BZOJ.4241.历史研究(回滚莫队 分块)
- [分块] BZOJ 4241 历史研究
- BZOJ 4241 历史研究
- bzoj 4241: 历史研究 分块
- 【bzoj4241】 历史研究
- BZOJ4241 历史研究
- 【bzoj4241】 历史研究
- bzoj 4241: 历史研究
- BZOJ 4241 历史研究
- BZOJ4241 历史研究