NBUT 1457 Sona (莫队算法)

来源:互联网 发布:网络聊天的问号和叹号 编辑:程序博客网 时间:2024/05/18 03:44

题意:

给出一个数列,求区间内相同数字次数的三次方和

分析:

离散化数字之后直接莫队


#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 100005struct node{    int l,r;    int id;} q[maxn];vector<int>v;long long ans[maxn];int vis[maxn];int a[maxn];int block[maxn];long long sum;bool cmp(node A,node B){    if(block[A.l]==block[B.l]) return A.r<B.r;    return block[A.l]<block[B.l];}long long cal(long long x){    return 3*x*x+3*x+1;}void update(int add,int note){    if(add==-1) sum-=cal(vis[note]-1),vis[note]--;    else sum+=cal(vis[note]),vis[note]++;}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        memset(vis,0,sizeof vis);        v.clear();        int bk=sqrt(n*1.0);        for(int i=1; i<=n; i++)        {            scanf("%d",&a[i]);            v.push_back(a[i]);            block[i]=(i/bk)+1;        }        block[n+1]=block[n]+1;        sort(v.begin(),v.end());        v.erase(unique(v.begin(),v.end()),v.end());        for(int i=1; i<=n; i++)        {            a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin();            a[i]++;        }        int m;        scanf("%d",&m);        for(int i=0; i<m; i++)        {            scanf("%d%d",&q[i].l,&q[i].r);            q[i].id=i;        }        sort(q,q+m,cmp);        int l=0,r=1;        sum=0;        for(int i=0; i<m; i++)        {            for(; r<=q[i].r; r++) update(1,a[r]);            for(; r-1>q[i].r; r--) update(-1,a[r-1]);            for(; l+1<q[i].l; l++) update(-1,a[l+1]);            for(; l>=q[i].l; l--) update(1,a[l]);            ans[q[i].id]=sum;        }        for(int i=0; i<m; i++)        {            printf("%I64d\n",ans[i]);        }    }    return 0;}


0 0
原创粉丝点击