洛谷P2709 小B的询问 莫队做法
需要注意的一点,一定要分块!不然会慢很多(直接TLE)
其中分块只在排序的时候要用,并且是给问题右端点分块
再就是注意add与del函数里的操作,增加数量不提,ans的加减可以用完全平方公式推出
上代码:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define NUM 50010 using namespace std; int n,m,k; long long ans,blo;//当前的答案,每个块内点的数量 int a[NUM]; long long sum[NUM],anss[NUM];//每个数的出现次数,对于每个问题的对应答案 struct wen{ long long l,r,num; }; wen q[NUM]; void add( int x ){ sum[a[x]]++; ans += sum[a[x]] * 2 - 1; } void del( int x ){ sum[a[x]]--; ans -= sum[a[x]] * 2 + 1; //a^2 = (a-1)^2+2a-1 } bool cmp( wen gu1,wen gu2 ){ if( gu1.r/blo != gu2.r/blo ) return gu1.r < gu2.r; return gu1.l < gu2.l; } int main(){ cin >> n >> m >> k; for( int i = 1;i <= n;i++ ) cin >> a[i]; for( int i = 1;i <= m;i++ ){ cin >> q[i].l >> q[i].r; q[i].num = i; } blo = sqrt(n); sort( q+1,q+m+1,cmp ); long long l = 1,r = 0,ql,qr; for( int i = 1;i <= m;i++ ){ ql = q[i].l;qr = q[i].r; while( l < ql ){ del(l); l++; } while( r > qr ){ del(r); r--; } //因为add函数是从a^2 = (a-1)^2 + 2a -1,所以先位移再跑函数 while( l > ql ){ l--; add(l); } while( r < qr ){ r++; add(r); } anss[q[i].num] = ans; } for( int i = 1;i <= m;i++ ) cout << anss[i] << endl; return 0; }