CodeForces 86D 莫队算法

来源:互联网 发布:淘宝精品推荐是什么 编辑:程序博客网 时间:2024/06/05 22:51

题意

如果一个区间内有1个2和3个1,那么这个区间的值就是1*1*2+3*3*1。进行T次询问,每次询问输出区间的值。

题解

问一个区间内有多少个X,这明显就是莫队的套路。没有太多好说的,直接直接套用一下莫队算法就能AC。

注意事项

CF真的坑,加了IO挂依然TLE。最后把sqrt(n)改成了sqrt(n*1.0)。瞬间就AC了。原本以为这两个计算结果会有不同,然后试了一下,N从0-5000万都计算了一下,这两个值是完全相同的,感觉好神奇。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#include<string>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define INF 0x3f3f3f3f#define LL long long#define MAXN 200010#define EPS 1e-10using namespace std;struct Node {    int l,r,id;    LL ans;};Node nodes[MAXN];int a[MAXN],num[1001000];int pos[MAXN];LL val;int n,t,q;int getint() {    int w=0;    char c=getchar();    W(c<'0'||c>'9') c=getchar();    W(c>='0'&&c<='9') {        w=w*10+c-'0';        c=getchar();    }    return w;}bool cmp(Node a,Node b) {    return pos[a.l]==pos[b.l]?a.r<b.r:a.l<b.l;}bool cmp1(Node a,Node b) {    return a.id<b.id;}void update(int x,int add) {    val-=(LL)num[a[x-1]]*num[a[x-1]]*a[x-1];    num[a[x-1]]+=add;    val+=(LL)num[a[x-1]]*num[a[x-1]]*a[x-1];//    cout<<x<<" "<<a[x-1]<<endl;}void solve() {    val=0;    int l=1,r=1;    update(1,1);    UP(i,0,t) {        for(; l<nodes[i].l; l++) update(l,-1);        for(; l>nodes[i].l; l--) update(l-1,1);        for(; r<nodes[i].r; r++) update(r+1,1);        for(; r>nodes[i].r; r--) update(r,-1);        nodes[i].ans=val;//        cout<<val<<endl;    }}int main() {    n=getint();    t=getint();    UP(i,0,n) a[i]=getint();    UP(i,0,t) {        nodes[i].l=getint();        nodes[i].r=getint();        nodes[i].id=i;    }    q=sqrt(1.0*n);    UP(i,0,n+1) pos[i]=i/q;    sort(nodes,nodes+t,cmp);    solve();    sort(nodes,nodes+t,cmp1);    UP(i,0,t) printf("%I64d\n",nodes[i].ans);}
原创粉丝点击