BZOJ 2308 h小Z的袜子(hose)(莫队经典)

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=2038/B

题意:

给你一个序列 a a a,每个不同 a [ i ] a[i] a[i]代表一种颜色,并给你一些查询 [ l , r ] [l,r] [l,r],问你在这个区间里随机选取两个元素,它们颜色相同的概率,以最简分数输出,若为0则以0/1形式输出;

分析:

首先需要两个变量分别维护分子和分母,不然没法使用莫队进行所谓的 O ( 1 ) O(1) O(1)的转化;那么 a n s 1 ans1 ans1记录分子, a n s 2 ans2 ans2记录分母, a n s 2 ans2 ans2很好求,对于每个区间 [ l , r ] [l,r] [l,r]来说可以直接求,即 a n s 2 = C r − l + 1 2 = ( r − l + 1 ) ∗ ( r − l ) / 2 ans2=C_{r-l+1}^2=(r-l+1)*(r-l)/2 ans2=Crl+12=(rl+1)(rl)/2,对于分子,如果是缩小区间(即指针向内靠近)则分子的一部分(因为可能有很多种颜色,这里只考虑指针移动位置的颜色的选择)由 C c o t [ a [ x ] ] 2 C_{cot[a[x]]}^2 Ccot[a[x]]2变成 C c o t [ a [ x ] ] − 1 2 C_{cot[a[x]]-1}^2 Ccot[a[x]]12,那么这个时候, a n s 1 ans1 ans1则是减少了 c o t [ a [ x ] ] − 1 cot[a[x]]-1 cot[a[x]]1,即 a n s 1 − = ( c o t [ a [ x ] ] − 1 ) ans1-=(cot[a[x]]-1) ans1=(cot[a[x]]1),若区间指针向外扩展,则有 C c o t [ a [ x ] ] 2 C_{cot[a[x]]}^2 Ccot[a[x]]2变成 C c o t [ a [ x ] ] + 1 2 C_{cot[a[x]]+1}^2 Ccot[a[x]]+12,这个时候有 a n s 1 + = c o t [ a [ x ] ] ans1+=cot[a[x]] ans1+=cot[a[x]],这即为两个关键操作,其中我也考虑过 c o t [ a [ x ] ] &lt; 2 cot[a[x]]&lt;2 cot[a[x]]<2的情况,然后发现想太多了,这种情况同样符合上述考虑;还有就是有几个位置注意爆int的问题,开long long;

代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>

using namespace std;

#define  inf 0x7f7f7f7f
#define  maxn 50009
#define  N 2
#define mod 100003

typedef long long ll;
typedef struct {
    int u, v, next, w;
} Edge;
Edge e[N];
int cnt, head[N];

inline void add1(int u, int v) {
    e[cnt].u = u;
    e[cnt].v = v;
    //e[cnt].w=w;
    // e[cnt].f=f;
    e[cnt].next = head[u];
    head[u] = cnt++;
    //e[cnt].u=v;
//    e[cnt].v=u;
//    e[cnt].w=0;
//    e[cnt].f=-f;
//    e[cnt].next=head[v];
//    head[v]=cnt++;
}

inline void write(int x) {
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}

inline int read() {
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')
            f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}

struct node {
    int l, r, id;
} p[maxn];
ll num, ans1, ans2, n, m, c[maxn], pos[maxn], cot[maxn], top[maxn], bot[maxn], ans[maxn][2];

bool com(node a, node b) {
    if (pos[a.l] != pos[b.l])return a.r < b.r;
    else return pos[a.l] < pos[b.l];
}

inline void del(int x) {
    cot[c[x]]--;
    ans1 -= cot[c[x]];
}

inline void add(int x) {
    ans1 += cot[c[x]];
    cot[c[x]]++;
}

inline ll _gcd(int a, int b) {
    return b == 0 ? a : _gcd(1ll * b, 1ll * a % b);
}

int main() {
    cin >> n >> m;
    int sz = sqrt(n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &c[i]);
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &p[i].l, &p[i].r);
        pos[i] = i / sz;
        p[i].id = i;
    }
    int l = 1, r = 0;
    sort(p + 1, p + 1 + m, com);
    for (int i = 1; i <= m; i++) {
        while (l < p[i].l) {
            del(l);
            l++;
        }
        while (l > p[i].l) {
            l--;
            add(l);
        }
        while (r < p[i].r) {
            r++;
            add(r);
        }
        while (r > p[i].r) {
            del(r);
            r--;
        }
        ans2 = 1ll * (r - l + 1) * (r - l) / 2;
        if (ans1 == 0) {
            top[p[i].id] = 0, bot[p[i].id] = 1;
            continue;
        }
        //cout<<ans1<<" "<<ans2<<endl;
        ll gcd = _gcd(ans1, ans2);
        top[p[i].id] = ans1 / gcd;
        bot[p[i].id] = ans2 / gcd;
    }
    for (int i = 1; i <= m; i++)
        cout << top[i] << "/" << bot[i] << endl;
    return 0;
}

我们坚持一件事情,并不是因为这样做了会有效果,而是坚信,这样做是对的。
——哈维尔

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园悬赏任务平台对字典管理、论坛管理、任务资讯任务资讯公告管理、接取用户管理、任务管理、任务咨询管理、任务收藏管理、任务评价管理、任务订单管理、发布用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行校园悬赏任务平台程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。校园悬赏任务平台的开发让用户查看任务信息变得容易,让管理员高效管理任务信息。 校园悬赏任务平台具有管理员角色,用户角色,这几个操作权限。 校园悬赏任务平台针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理任务信息,管理任务资讯公告信息等内容。 校园悬赏任务平台针对用户设置的功能有:查看并修改个人信息,查看任务信息,查看任务资讯公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看任务,删除任务操作,新增任务操作,修改任务操作。任务资讯公告信息管理页面提供的功能操作有:新增任务资讯公告,修改任务资讯公告,删除任务资讯公告操作。任务资讯公告类型管理页面显示所有任务资讯公告类型,在此页面既可以让管理员添加新的任务资讯公告信息类型,也能对已有的任务资讯公告类型信息执行编辑更新,失效的任务资讯公告类型信息也能让管理员快速删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值