bzoj 3781
又忘了给每个点标所属的块,瞬间就变成一个块了。
写莫队一定要试一下随机极限数据。
1 /************************************************************** 2 Problem: 3781 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1184 ms 7 Memory:2772 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <cmath> 13 #include <algorithm> 14 #define maxn 50010 15 using namespace std; 16 17 typedef long long lng; 18 19 int n, m, k; 20 int w[maxn]; 21 int mccno[maxn], lx[maxn], rx[maxn], stot; 22 int cnt[maxn]; 23 lng ans[maxn], cur_ans; 24 25 struct Qu { 26 int l, r, id; 27 bool operator<( const Qu & b ) const { 28 return mccno[l]<mccno[b.l] || (mccno[l]==mccno[b.l] && r<b.r ); 29 } 30 }; 31 Qu qu[maxn]; 32 33 void init() { 34 memset( cnt, 0, sizeof(cnt) ); 35 cur_ans = 0; 36 } 37 void add( int v ) { 38 cur_ans -= cnt[v]*cnt[v]; 39 cnt[v]++; 40 cur_ans += cnt[v]*cnt[v]; 41 } 42 void del( int v ) { 43 cur_ans -= cnt[v]*cnt[v]; 44 cnt[v]--; 45 cur_ans += cnt[v]*cnt[v]; 46 } 47 48 void partition() { 49 int len = (int)sqrt(n)+1; 50 int stot = n/len; 51 rx[0] = 0; 52 for( int i=1; i<=stot; i++ ) { 53 lx[i] = rx[i-1]+1; 54 rx[i] = rx[i-1]+len; 55 } 56 if( rx[stot]!=n ) { 57 stot++; 58 rx[stot] = n; 59 lx[stot] = rx[stot-1]+1; 60 } 61 for( int i=1; i<=stot; i++ ) 62 for( int j=lx[i]; j<=rx[i]; j++ ) 63 mccno[j] = i; 64 } 65 66 void work() { 67 sort( qu+1, qu+1+m ); 68 for( int q=1,lf,rg; q<=m; q++ ) { 69 if( q==1 || mccno[qu[q].l]!=mccno[qu[q-1].l] ) { 70 lf = qu[q].l; 71 rg = lf-1; 72 init(); 73 } 74 while( lf<qu[q].l ) del( w[lf++] ); 75 while( lf>qu[q].l ) add( w[--lf] ); 76 while( rg<qu[q].r ) add( w[++rg] ); 77 while( rg>qu[q].r ) del( w[rg--] ); 78 ans[qu[q].id] = cur_ans; 79 } 80 } 81 82 int main() { 83 scanf( "%d%d%d", &n, &m, &k ); 84 for( int i=1; i<=n; i++ ) 85 scanf( "%d", w+i ); 86 for( int i=1; i<=m; i++ ) { 87 scanf( "%d%d", &qu[i].l, &qu[i].r ); 88 qu[i].id = i; 89 } 90 partition(); 91 work(); 92 for( int i=1; i<=m; i++ ) 93 printf( "%lld\n", ans[i] ); 94 } 95 96