题意
如果一个区间内有1个2和3个1,那么这个区间的值就是1*1*2+3*3*1。进行T次询问,每次询问输出区间的值。
题解
问一个区间内有多少个X,这明显就是莫队的套路。没有太多好说的,直接直接套用一下莫队算法就能AC。
注意事项
CF真的坑,加了IO挂依然TLE。最后把sqrt(n)改成了sqrt(n*1.0)。瞬间就AC了。原本以为这两个计算结果会有不同,然后试了一下,N从0-5000万都计算了一下,这两个值是完全相同的,感觉好神奇。
代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#include<set>
#include<map>
#include<bitset>
#include<stack>
#include<string>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(a) while(a)
#define MEM(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
#define MAXN 200010
#define EPS 1e-10
using namespace std;
struct Node {
int l,r,id;
LL ans;
};
Node nodes[MAXN];
int a[MAXN],num[1001000];
int pos[MAXN];
LL val;
int n,t,q;
int getint() {
int w=0;
char c=getchar();
W(c<'0'||c>'9') c=getchar();
W(c>='0'&&c<='9') {
w=w*10+c-'0';
c=getchar();
}
return w;
}
bool cmp(Node a,Node b) {
return pos[a.l]==pos[b.l]?a.r<b.r:a.l<b.l;
}
bool cmp1(Node a,Node b) {
return a.id<b.id;
}
void update(int x,int add) {
val-=(LL)num[a[x-1]]*num[a[x-1]]*a[x-1];
num[a[x-1]]+=add;
val+=(LL)num[a[x-1]]*num[a[x-1]]*a[x-1];
// cout<<x<<" "<<a[x-1]<<endl;
}
void solve() {
val=0;
int l=1,r=1;
update(1,1);
UP(i,0,t) {
for(; l<nodes[i].l; l++) update(l,-1);
for(; l>nodes[i].l; l--) update(l-1,1);
for(; r<nodes[i].r; r++) update(r+1,1);
for(; r>nodes[i].r; r--) update(r,-1);
nodes[i].ans=val;
// cout<<val<<endl;
}
}
int main() {
n=getint();
t=getint();
UP(i,0,n) a[i]=getint();
UP(i,0,t) {
nodes[i].l=getint();
nodes[i].r=getint();
nodes[i].id=i;
}
q=sqrt(1.0*n);
UP(i,0,n+1) pos[i]=i/q;
sort(nodes,nodes+t,cmp);
solve();
sort(nodes,nodes+t,cmp1);
UP(i,0,t) printf("%I64d\n",nodes[i].ans);
}