您的位置:首页 > 其它

NBUT 1457 Sona (莫队算法)

2016-08-05 15:36 197 查看
题意:

给出一个数列,求区间内相同数字次数的三次方和

分析:

离散化数字之后直接莫队

#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 100005

struct node
{
int l,r;
int id;
} q[maxn];

vector<int>v;
long long ans[maxn];
int vis[maxn];
int a[maxn];
int block[maxn];
long long sum;

bool cmp(node A,node B)
{
if(block[A.l]==block[B.l]) return A.r<B.r;
return block[A.l]<block[B.l];
}

long long cal(long long x)
{
return 3*x*x+3*x+1;
}

void update(int add,int note)
{
if(add==-1) sum-=cal(vis[note]-1),vis[note]--;
else sum+=cal(vis[note]),vis[note]++;
}

int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(vis,0,sizeof vis);
v.clear();
int bk=sqrt(n*1.0);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
v.push_back(a[i]);
block[i]=(i/bk)+1;
}
block[n+1]=block
+1;
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1; i<=n; i++)
{
a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin();
a[i]++;
}
int m;
scanf("%d",&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q,q+m,cmp);
int l=0,r=1;
sum=0;
for(int i=0; i<m; i++)
{
for(; r<=q[i].r; r++) update(1,a[r]);
for(; r-1>q[i].r; r--) update(-1,a[r-1]);
for(; l+1<q[i].l; l++) update(-1,a[l+1]);
for(; l>=q[i].l; l--) update(1,a[l]);
ans[q[i].id]=sum;
}
for(int i=0; i<m; i++)
{
printf("%I64d\n",ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: