BZOJ3781小B的询问

莫队裸题。

维护的时候有的打法是利用(a-1)^2==a^2-2*a+1转移,也可以,但是通用性不太够。

下面的打法就是先把这个点的贡献删掉,然后更新这个点,再把这个点的贡献加回来,这种解法更加通用一些。

剩下的是我分块的时候i/part打成n/part了,TLE30,改了就A了,还是要注意对拍呀。

#include<bits/stdc++.h>
using namespace std;
struct MoCap{
    int l,r,id;
}q[50005];
int n,m,k,ans[50005],part,ans1,sum[50005],col[50005],bl[50005];
int read(){
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }return sum*f;
}
bool cmp(MoCap a,MoCap b){
    return (bl[a.l]^bl[b.l])?bl[a.l]<bl[b.l]:((bl[a.l]&1)?a.r<b.r:a.r>b.r);
}
void updata(int i,int val){
    ans1-=sum[col[i]]*sum[col[i]];
    sum[col[i]]+=val;
    ans1+=sum[col[i]]*sum[col[i]];
}
int main(){
    n=read();m=read();k=read();part=sqrt(n);
    for(int i=1;i<=n;i++){
        col[i]=read();
        bl[i]=i/part+1;
    }
    for(int i=1;i<=m;i++){
        q[i].l=read();q[i].r=read();
        q[i].id=i;
    }sort(q+1,q+1+m,cmp);
    int l=1,r=0;
//    cout<<endl;
    for(int i=1;i<=m;i++){
        while(l<q[i].l) updata(l++,-1);
        while(l>q[i].l) updata(--l,1);
        while(r<q[i].r) updata(++r,1);
        while(r>q[i].r) updata(r--,-1);
    //    cout<<q[i].id<<" "<<ans1<<endl;
    //    for(int j=1;j<=n;j++)
    //        cout<<sum[col[j]]<<" ";cout<<endl;
        ans[q[i].id]=ans1;
    }
    for(int i=1;i<=m;i++)
        printf("%d
",ans[i]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Yu-shi/p/11240999.html