bzoj 3781 小B的询问(莫队算法)
【题意】
若干个询问sigma{ cnt[i]^2 } cnt[i]表示i在[l,r]内的出现次数。
【思路】
莫队算法,裸题。
一个cnt数组即可维护插入与删除。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 using namespace std; 12 13 typedef long long ll; 14 const int N = 5e5+10; 15 16 ll read() 17 { 18 char c=getchar(); 19 ll f=1,x=0; 20 while(!isdigit(c)) { 21 if(c=='-') f=-1; c=getchar(); 22 } 23 while(isdigit(c)) 24 x=x*10+c-'0',c=getchar(); 25 return x*f; 26 } 27 28 struct Node 29 { 30 int id,pos,l,r; 31 bool operator < (const Node& rhs) const 32 { 33 return pos<rhs.pos || (pos==rhs.pos&&r<rhs.r); 34 } 35 } q[N]; 36 37 int n,m,K,a[N]; ll ans[N],cnt[N],now; 38 39 void upd(int x,int v) 40 { 41 now-=cnt[a[x]]*cnt[a[x]]; 42 cnt[a[x]]+=v; 43 now+=cnt[a[x]]*cnt[a[x]]; 44 } 45 46 int main() 47 { 48 // freopen("in.in","r",stdin); 49 // freopen("out.out","w",stdout); 50 n=read(),m=read(),K=read(); 51 FOR(i,1,n) a[i]=read(); 52 int B=sqrt(n); 53 FOR(i,1,m) 54 { 55 q[i].l=read(), 56 q[i].r=read(); 57 q[i].id=i; 58 q[i].pos=(q[i].l-1)/B+1; 59 } 60 sort(q+1,q+m+1); 61 int l=1,r=0; 62 FOR(i,1,m) 63 { 64 while(l<q[i].l) upd(l++,-1); 65 while(l>q[i].l) upd(--l,1); 66 while(r>q[i].r) upd(r--,-1); 67 while(r<q[i].r) upd(++r,1); 68 ans[q[i].id]=now; 69 } 70 FOR(i,1,m) printf("%lld\n",ans[i]); 71 return 0; 72 }
posted on 2016-04-01 09:38 hahalidaxin 阅读(231) 评论(0) 编辑 收藏 举报