BZOJ 2038 小Z的袜子(莫队算法)

来源:互联网 发布:网络直播主持稿 编辑:程序博客网 时间:2024/06/12 01:37
莫队算法的话,看这个比较好懂:http://blog.csdn.net/bossup/article/details/39236275不过这里面的博客的代码貌似有点问题,所以代码的话,http://blog.csdn.net/lwt36/article/details/50583757这个是对的,看我的也行。什么时候用莫队?1、区间不会被修改2、可以离线3、对于[L,R],可以直接退出[L,R+1],[L,R-1],[L+1,R],[L-1,R]4、数据规模合适,莫队的复杂度nsqrt(n)

题意:

题意我就不说了,其实这题对于公式的化简也算是一个难点,不过,都把他当做莫队的模板题,所以也就忽视了推导过程。对于L,R的询问。设其中颜色为x,y,z....的袜子的个数为a,b,c。。。那么答案即为(a*(a-1)/2+b*(b-1)/2+c*(c-1)/2....)/((R-L+1)*(R-L)/2)化简得:(a^2+b^2+c^2+...x^2-(a+b+c+d+.....))/((R-L+1)*(R-L))即:(a^2+b^2+c^2+...x^2-(R-L+1))/((R-L+1)*(R-L))这就是推导过程,恩,看了就懂了。

莫队有一个关键,就是块内的r是上升的,一定要记住,不然和暴力
就没区别了。
我已开始排序的时候写成这样:

struct Query{    int l,r,id;    Query(int l,int r,int id):l(l),r(r),id(id){}    bool operator < (const Query& rhs) const {        return l==rhs.l?r<rhs.r:l<rhs.l;    }};

结果T到死。
代码:

////  Created by  CQU_CST_WuErli//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.//// #include<bits/stdc++.h>#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <cctype>#include <cmath>#include <string>#include <vector>#include <list>#include <map>#include <queue>#include <stack>#include <set>#include <algorithm>#include <sstream>#define CLR(x) memset(x,0,sizeof(x))#define OFF(x) memset(x,-1,sizeof(x))#define MEM(x,a) memset((x),(a),sizeof(x))#define For_UVa if (kase!=1) cout << endl#define BUG cout << "I am here" << endl#define lookln(x) cout << #x << "=" << x << endl#define SI(a) scanf("%d",&a)#define SII(a,b) scanf("%d%d",&a,&b)#define SIII(a,b,c) scanf("%d%d%d",&a,&b,&c)#define rep(flag,start,end) for(int flag=start;flag<=end;flag++)#define Rep(flag,start,end) for(int flag=start;flag>=end;flag--)#define Lson l,mid,rt<<1#define Rson mid+1,r,rt<<1|1#define Root 1,n,1#define BigInteger bignconst int MAX_L=2005;// For BigIntegerconst int INF_INT=0x3f3f3f3f;const long long INF_LL=0x7fffffff;const int MOD=1e9+7;const double eps=1e-9;const double pi=acos(-1);typedef long long  ll;using namespace std;inline int read() {    char c = getchar();    while(!isdigit(c)) c = getchar();    int x = 0;    while(isdigit(c)) {        x = x * 10 + c - '0';        c = getchar();    }    return x;}const int N=5e4+10;const int M=250;int n,m;int c[N];int num[N];ll ans,up[N],dw[N];struct Query{    int l,r,id;    Query(int l,int r,int id):l(l),r(r),id(id){}    bool operator < (const Query& rhs) const {        return r<rhs.r;    }};vector<Query> block[M];void update(int x,int d) {    ans-=num[c[x]]*num[c[x]];    num[c[x]]+=d;    ans+=num[c[x]]*num[c[x]];}int main() {#ifdef LOCAL    freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);    // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);#endif    while(SII(n,m)==2) {        rep(i,0,250) block[i].clear();        rep(i,0,n-1) c[i]=read();        rep(i,1,m) {            int l,r;            l=read();r=read();            l--,r--;            block[l/M].push_back(Query(l,r,i));        }        ans=0LL;        CLR(num);        rep(i,0,n/M+2) sort(block[i].begin(),block[i].end());        int pL,pR;        rep(i,0,n/M+2) if (block[i].size()) {            pL=i*M;            pR=i*M-1;            rep(j,0,block[i].size()-1) {                Query &q=block[i][j];                if (pR<q.r) rep(k,pR+1,q.r) update(k,1);                else Rep(k,pR,q.r+1) update(k,-1);                pR=q.r;                if (pL<q.l) rep(k,pL,q.l-1) update(k,-1);                else Rep(k,pL-1,q.l) update(k,1);                pL=q.l;                up[q.id]=ans-q.r+q.l-1;                dw[q.id]=1LL*(q.r-q.l)*(q.r-q.l+1);                // cout << up[q.id] << ' ' << dw[q.id] << endl;                ll tmp=__gcd(up[q.id],dw[q.id]);                up[q.id]/=tmp;                dw[q.id]/=tmp;            }            rep(j,pL,pR) update(j,-1);        }        rep(i,1,m) printf("%lld/%lld\n",up[i],dw[i]);    }    return 0;}
0 0
原创粉丝点击