题意:求某段区间内数字出现次数的立方和.
分析:莫队的模板题,不得不说这题神坑,vj说好的操作系统为Linux呢???结果%I64d才能过==
当然这题不用输入挂其实也能过~
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e5+10;
int n,m,sz;
int note[maxn];
int a[maxn];
int pos[maxn];
int f[maxn];
struct Query{
int l,r;
int id;
LL ans;
bool operator < ( const Query &q)const
{
if( pos[l] == pos[q.l])
return r < q.r;
return pos[l] < pos[q.l];
}
}q[maxn];
inline void scanf_(int &num){
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-'){
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
}
bool cmp( const Query &q1, const Query &q2)
{
return q1.id < q2.id;
}
void Modify( int p, LL &ans, int tag)
{
ans -= (LL)f[a[p]]*f[a[p]]*f[a[p]];
f[a[p]] += tag;
ans += (LL)f[a[p]]*f[a[p]]*f[a[p]];
}
int main()
{
while( ~scanf("%d",&n))
{
mem(f,0);
int limit = (int)sqrt(n*1.0);
for( int i = 1; i <= n; i++)
{
// scanf("%lld",¬e[i]);
scanf_(note[i]);
a[i] = note[i];
pos[i] = (i-1)/limit+1;
}
// scanf("%d",&m);
scanf_(m);
for( int i = 1; i <= m; i++)
{
// scanf("%d%d",&q[i].l,&q[i].r);
scanf_(q[i].l);
scanf_(q[i].r);
q[i].id = i;
}
sort(note+1,note+1+n);
sz = unique(note+1,note+1+n)-note;//去重
for( int i = 1; i <= n; i++)
a[i] = lower_bound(note+1,note+sz,a[i])-note;
sort(q+1,q+1+m);
int l = 1, r = 0;
LL tmp = 0;
for( int i = 1; i <= m; i++)//不断逼近区间
{
if( r < q[i].r)
{
for( r = r+1; r < q[i].r; r++)
Modify(r,tmp,1);
Modify(r,tmp,1);
}
if( q[i].l < l)
{
for( l = l-1; l > q[i].l; l--)
Modify(l,tmp,1);
Modify(l,tmp,1);
}
if( q[i].r < r)
{
for( ; r > q[i].r; r--)
Modify(r,tmp,-1);
}
if( l < q[i].l)
{
for( ; l < q[i].l; l++)
Modify(l,tmp,-1);
}
if( q[i].l == q[i].r)
{
q[i].ans = 1;
continue;
}
q[i].ans = tmp;
}
sort(q+1,q+1+m,cmp);
for( int i = 1; i <= m; i++)
printf("%I64d\n",q[i].ans);//一定要用%I64d输出啊
}
return 0;
}