BZOJ2038 小Z的袜子(莫队之源)

题意+思路:

给你m个区间询问,问每个区间内的$\displaystyle \frac{\sum x^2-(R-L+1)}{(R-L)(R-L+1)} $,其中x为每种数字的个数,用cnt存储;

所以我们需要用莫队处理每个区间的$\displaystyle \sum x^2 $

相邻状态转移如果是$O(i)$,复杂度就为$O(in\sqrt{n})$,因为这里状态转移是$O(1)$的,所以复杂度为$O(n\sqrt{n})$

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-5;
const int mod = 1e9+7;
const int maxn = 3e5+2;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);

inline ll gcd(ll a, ll b){
    return b==0?a:gcd(b,a%b);
}
int block;
ll res;//存储sigma x^2
struct Blc{
    int l, r;
    int id;
    bool operator < (const Blc &b)const{
        if(l/block == b.l/block) return r < b.r;
        return l/block < b.l/block;
    }
}blc[maxn];
int a[maxn];
ll cnt[maxn];
ll ansx[maxn], ansy[maxn];//储存答案x/y

void insert(int x){
    res -= cnt[x]*cnt[x];
    cnt[x]++;
    res += cnt[x]*cnt[x];
    return;
}

void remove(int x){
    res -= cnt[x]*cnt[x];
    cnt[x]--;
    res += cnt[x]*cnt[x];
    return;
}

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    block = sqrt(n);
    for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
    for(int i = 0; i < m; i++){
        blc[i].id=i;
        scanf("%d %d", &blc[i].l, &blc[i].r);
    }
    mem(cnt, 0);
    sort(blc, blc+m);
    int l, r;
    l = r = 1;//光标
    cnt[a[1]]++;
    res = 1;
    for(int i = 0; i < m; i++){
        int id = blc[i].id;
        if(blc[i].l==blc[i].r){
            ansx[id] = 0;
            ansy[id] = 1;
            continue;
        }
        while(l < blc[i].l) remove(a[l++]);
        while(l > blc[i].l) insert(a[--l]);
        while(r < blc[i].r) insert(a[++r]);
        while(r > blc[i].r) remove(a[r--]);

        ll x, y, g;
        x = res - (blc[i].r - blc[i].l + 1);
        y = (blc[i].r - blc[i].l)*(blc[i].r - blc[i].l + 1ll);
        g = gcd(y, x);
        ansx[id] = x/g;
        ansy[id] = y/g;
    }
    for(int i = 0; i < m; i++){
        printf("%lld/%lld\n", ansx[i], ansy[i]);
    }
    return 0;
}

 

posted @ 2018-08-29 02:34  wrjlinkkkkkk  阅读(144)  评论(0编辑  收藏  举报