zoukankan      html  css  js  c++  java
  • bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队算法

    题目链接

    给n个数, m个询问, 每个询问有[L, R]两个值, 在这段区间内取两个数,求这两个数相同的概率。

    对于区间[L, R], 概率的分母显然是(R-L+1)*(R-L)/2, 对于分子, 假设我们已经有了一个1, 又遇到了一个1, 那么这时分子应该加上(2*1)/2, 假如又遇到了一个1, 那么分子应该减去(2*1)/2然后在加上(3*2)/2。

    因为只有查询而没有修改, 所以我们可以离线做, 先将每一个区间读入, 然后将其排序,一开始的区间是[L, R], 对于下一个区间[L', R'], 只需要考虑[L, L']或[L', L]这一部分以及[R, R']或[R', R]这一部分。

    分子就是这段区间内的sigma(s[i]*s[i-1])/2, s[i]是每一个数出现的次数。具体看代码。

    注意会爆int

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define pb(x) push_back(x)
      4 #define ll long long
      5 #define mk(x, y) make_pair(x, y)
      6 #define lson l, m, rt<<1
      7 #define mem(a) memset(a, 0, sizeof(a))
      8 #define rson m+1, r, rt<<1|1
      9 #define mem1(a) memset(a, -1, sizeof(a))
     10 #define mem2(a) memset(a, 0x3f, sizeof(a))
     11 #define rep(i, a, n) for(int i = a; i<n; i++)
     12 #define ull unsigned long long
     13 typedef pair<int, int> pll;
     14 const double PI = acos(-1.0);
     15 const double eps = 1e-8;
     16 const int mod = 1e9+7;
     17 const int inf = 1061109567;
     18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
     19 const int maxn = 50005;
     20 int a[maxn], b[maxn], ans[maxn][2];
     21 struct node
     22 {
     23     int block, r, l, id;
     24     bool operator < (node a)const
     25     {
     26         if(block == a.block)
     27             return r<a.r;
     28         return block<a.block;
     29     }
     30 }q[maxn];
     31 ll gcd(ll a, ll b) {
     32     return b==0?a:gcd(b, a%b);
     33 }
     34 void get(int l, int r, int id, ll tmp) {
     35     if(tmp == 0) {
     36         ans[id][0] = 0;
     37         ans[id][1] = 1;
     38     } else {
     39         ll g = gcd(tmp, 1ll*(r-l+1)*(r-l));
     40         ans[id][0] = tmp/g;
     41         ans[id][1] = 1ll*(r-l+1)*(r-l)/g;
     42     }
     43 }
     44 int main()
     45 {
     46     int n, m;
     47     while(~scanf("%d%d", &n, &m)) {
     48         mem(b);
     49         for(int i = 1; i<=n; i++) {
     50             scanf("%d", &a[i]);
     51         }
     52         int BLOCK = sqrt(n*1.0);
     53         for(int i = 0; i<m; i++) {
     54             scanf("%d%d", &q[i].l, &q[i].r);
     55             q[i].block = q[i].l/BLOCK;
     56             q[i].id = i;
     57         }
     58         sort(q, q+m);
     59         ll tmp = 0;
     60         for(int i = q[0].l; i<=q[0].r; i++) {
     61             tmp -= 1ll*b[a[i]]*(b[a[i]]-1);
     62             b[a[i]]++;
     63             tmp += 1ll*b[a[i]]*(b[a[i]]-1);
     64         }
     65         get(q[0].l, q[0].r, q[0].id, tmp);
     66         for(int i = 1; i<m; i++) {
     67             if(q[i].l<q[i-1].l) {
     68                 for(int j = q[i-1].l-1; j>=q[i].l; j--) {
     69                     tmp -= 1ll*b[a[j]]*(b[a[j]]-1);
     70                     b[a[j]]++;
     71                     tmp += 1ll*b[a[j]]*(b[a[j]]-1);
     72                 }
     73             } else {
     74                 for(int j = q[i-1].l; j<q[i].l; j++) {
     75                     tmp -= 1ll*b[a[j]]*(b[a[j]]-1);
     76                     b[a[j]]--;
     77                     tmp += 1ll*b[a[j]]*(b[a[j]]-1);
     78                 }
     79             }
     80             if(q[i].r>q[i-1].r) {
     81                 for(int j = q[i-1].r+1; j<=q[i].r; j++) {
     82                     tmp -= 1ll*b[a[j]]*(b[a[j]]-1);
     83                     b[a[j]]++;
     84                     tmp += 1ll*b[a[j]]*(b[a[j]]-1);
     85                 }
     86             } else {
     87                 for(int j = q[i-1].r; j>q[i].r; j--) {
     88                     tmp -= 1ll*b[a[j]]*(b[a[j]]-1);
     89                     b[a[j]]--;
     90                     tmp += 1ll*b[a[j]]*(b[a[j]]-1);
     91                 }
     92             }
     93             get(q[i].l, q[i].r, q[i].id, tmp);
     94         }
     95         for(int i = 0; i<m; i++) {
     96             printf("%d/%d
    ", ans[i][0], ans[i][1]);
     97         }
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    家长如何助力孩子适应小学生活
    一年级线上家长会
    gdb常用调试命令
    二叉树-后序遍历
    机器人
    Oracle创建只读账号的详细步骤
    ORACLE RAC日常运维-调整RAC+DG环境redo大小
    Redis 延迟分析
    oracle dataguard 重启步骤
    catalog start with + switch database to copy的妙用
  • 原文地址:https://www.cnblogs.com/yohaha/p/5057152.html
Copyright © 2011-2022 走看看