• [bzoj2038 [2009国家集训队]小Z的袜子(hose)] 莫队算法


    题意:Q个询问,每个询问给定区间[L,R],求从里面任选两个数相同的概率。

    思路:莫队算法。用一个cnt数组记录当前区间每种数的个数,区间变化为1时O(1)的维护cnt数组,并可以O(1)的得到当前区间中与当前数相同的数的个数。

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    #pragma comment(linker, "/STACK:10240000")
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define copy(a, b)          memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    //#ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    //#endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    
    const double PI = acos(-1.0);
    const int INF = 1e9 + 7;
    const double EPS = 1e-8;
    
    /* -------------------------------------------------------------------------------- */
    
    const int maxn = 5e4 + 7;
    
    pair<pii, int> qry[maxn];
    int a[maxn], block, cnt[maxn];
    pair<ll, ll> ans[maxn];
    
    ll gcd(ll a, ll b) {
        return b? gcd(b, a % b) : a;
    }
    bool cmp(const pair<pii, int> &a, const pair<pii, int> &b) {
        int lb = a.X.X / block, rb = b.X.X / block;
        return lb == rb? a.X.Y < b.X.Y : lb < rb;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n, m;
        while (cin >> n >> m) {
            block = (int)sqrt(n * 1.0 + 0.5);
            for (int i = 0; i < n; i ++) {
                scanf("%d", a + i);
            }
            for (int i = 0; i < m; i ++) {
                scanf("%d%d", &qry[i].X.X, &qry[i].X.Y);
                qry[i].X.X --;
                qry[i].X.Y --;
                qry[i].Y = i;
            }
            sort(qry, qry + m, cmp);
            fillchar(cnt, 0);
            int lastl = 0, lastr = 0;
            ll lastans = 0;
            cnt[a[0]] ++;
            for (int i = 0; i < m; i ++) {
                while (qry[i].X.X < lastl) lastans += cnt[a[-- lastl]] ++;
                while (qry[i].X.Y > lastr) lastans += cnt[a[++ lastr]] ++;
                while (qry[i].X.X > lastl) lastans -= -- cnt[a[lastl ++]];
                while (qry[i].X.Y < lastr) lastans -= -- cnt[a[lastr --]];
                ll n = qry[i].X.Y - qry[i].X.X + 1, buf = n * (n - 1) / 2;
                ll g = gcd(lastans, buf);
                if (lastans) ans[qry[i].Y] = mp(lastans / g, buf / g);
                else ans[qry[i].Y] = mp(0, 1);
            }
            for (int i = 0; i < m; i ++) {
                printf("%lld/%lld
    ", ans[i].X, ans[i].Y);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    spring中的切入点
    spring AOP的基本概念
    sql server 批量修改数据表和存储过程的所有者(2000)或架构(2005)
    SQL SERVER 修改欄位(列)屬性或是名稱
    sql server 數據庫備份與還原 登錄名丟失 解決辦法
    开心农场给我们的20条人生启示
    sql建立遠端聯接
    windows无法存取指定的装置、路径或文件案
    Vs.net 2008 最搞笑的問題
    女儿长大了!
  • 原文地址:https://www.cnblogs.com/jklongint/p/4733203.html
Copyright © 2020-2023  润新知