您的位置:首页 > 其它

bzoj 3781 小B的询问(莫队算法)

2016-04-01 09:38 218 查看
【题意】

若干个询问sigma{ cnt[i]^2 } cnt[i]表示i在[l,r]内的出现次数。

【思路】

莫队算法,裸题。

一个cnt数组即可维护插入与删除。

【代码】

#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std;

typedef long long ll;
const int N = 5e5+10;

ll read()
{
char c=getchar();
ll f=1,x=0;
while(!isdigit(c)) {
if(c=='-') f=-1; c=getchar();
}
while(isdigit(c))
x=x*10+c-'0',c=getchar();
return x*f;
}

struct Node
{
int id,pos,l,r;
bool operator < (const Node& rhs) const
{
return pos<rhs.pos || (pos==rhs.pos&&r<rhs.r);
}
} q
;

int n,m,K,a
; ll ans
,cnt
,now;

void upd(int x,int v)
{
now-=cnt[a[x]]*cnt[a[x]];
cnt[a[x]]+=v;
now+=cnt[a[x]]*cnt[a[x]];
}

int main()
{
//    freopen("in.in","r",stdin);
//    freopen("out.out","w",stdout);
n=read(),m=read(),K=read();
FOR(i,1,n) a[i]=read();
int B=sqrt(n);
FOR(i,1,m)
{
q[i].l=read(),
q[i].r=read();
q[i].id=i;
q[i].pos=(q[i].l-1)/B+1;
}
sort(q+1,q+m+1);
int l=1,r=0;
FOR(i,1,m)
{
while(l<q[i].l) upd(l++,-1);
while(l>q[i].l) upd(--l,1);
while(r>q[i].r) upd(r--,-1);
while(r<q[i].r) upd(++r,1);
ans[q[i].id]=now;
}
FOR(i,1,m) printf("%lld\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: