Codeforces 86D 莫队算法
https://codeforc.es/contest/86/problem/D
题意:
问一些区间[l,r]内所有至少一次的数字*该数字的出现次数^2之和
题解:
裸题,复习一下莫队,
根号算法果然很慢..2e5跑了2.5s
#include <bits/stdc++.h> #define endl '\n' #define ll long long #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<int,int> #define all(x) x.begin(),x.end() #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) using namespace std; const int maxn=2e6+10,maxm=2e6+10; int casn,n,m,k; ll a[maxn],ans[maxn],sz,sum; class block{public: ll cnt[maxn]; struct node{ ll l,r,id; bool operator <(const node &b)const { if(l/sz!=b.l/sz) return l<b.l; if((l/sz)&1) return r<b.r; return r>b.r; } }; void update(int pos,ll flag=1){ sum+=flag*a[pos]*(cnt[a[pos]]*2ll+flag); cnt[a[pos]]+=flag; } }ask; vector<block::node> tab; int main() { IO; cin>>n>>m;sz=sqrt(n); rep(i,1,n) cin>>a[i]; rep(i,1,m) { int a,b;cin>>a>>b; tab.push_back({a,b,i}); } sort(all(tab)); int l=tab[0].l,r=tab[0].l-1; for(auto now:tab){ while(l>now.l) ask.update(--l,1); while(l<now.l) ask.update(l++,-1); while(r<now.r) ask.update(++r,1); while(r>now.r) ask.update(r--,-1); ans[now.id]=sum; } rep(i,1,m) cout<<ans[i]<<endl; return 0; }