Codeforces 86D 莫队算法

https://codeforc.es/contest/86/problem/D

题意:

问一些区间[l,r]内所有至少一次的数字*该数字的出现次数^2之和

题解:

裸题,复习一下莫队,

根号算法果然很慢..2e5跑了2.5s

#include <bits/stdc++.h>
#define endl '
'
#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;
}
原文地址:https://www.cnblogs.com/nervendnig/p/10859092.html