1 条题解
-
0Takagi-san (njnu19200437) LV 10 MOD @ 2022-01-30 23:32:58
本题是经典的莫队(Mo's Algorithm),因为区间左右移动对答案的影响可以在\(O(1)\)时间内算出。
莫队的核心思想是对各个询问作合理的排序,然后进行\(O(n\sqrt n)\)数量级次移动(左区间+1,-1或右区间+1,-1称为一次移动),每次移动的代价是\(O(1)\),所以总的时间复杂度是\(O(n\sqrt n)\)Code:
#include <bits/stdc++.h> using namespace std; const int siz = 2000, maxval = 5e5+5; struct query{ int l, r, index; bool operator< (const query& q) { if(l/siz != q.l/siz) return l/siz < q.l/siz; return r/siz < q.r/siz; } }; int nowl = 1, nowr = 0; //初始没有元素,初始区间[1,0] long long nowans = 0; long long num[maxval]; void ins(int x){num[x]++; nowans+=num[x]-1;} void del(int x){num[x]--; nowans-=num[x];} int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, k, q; cin>>n>>k>>q; long long a[n+1], pre[n+1] = {0}; for(int i=1;i<=n;i++) cin>>a[i]; partial_sum(a+1, a+n+1, pre+1); for(auto& i: pre) i%=k; query Q[q]; long long ans[q]; for(int i=0;i<q;i++) cin>>Q[i].l>>Q[i].r, Q[i].index = i; sort(Q,Q+q); for(auto [l, r, index] : Q) // C++17及以上支持结构化绑定 { while(nowr < r) ins(pre[++nowr]); while(nowl > l) ins(pre[--nowl]); while(nowr > r) del(pre[nowr--]); while(nowl < l) del(pre[nowl++]); ans[index] = nowans + num[pre[l-1]]; } for(auto i: ans) cout<<i<<'\n'; return 0; }
- 1
信息
- ID
- 1316
- 难度
- 9
- 分类
- (无)
- 标签
- (无)
- 递交数
- 90
- 已通过
- 3
- 通过率
- 3%
- 被复制
- 1
- 上传者