P1494 [国家集训队]小Z的袜子

P1494 [国家集训队]小Z的袜子

(洛谷没能交上去,就先放在博客里了)

这是个模板题

莫队的话,我学得别人,整了两个指针L和R

然后每个询问得话,就是让我们求:

从颜色相同的袜子里取两只的方案,然后再去除以这段从这段区间里随意取两只的方案

这怎么处理呢?当然可以用组合数直接求出来

而且,组合数只需要开C[N][3]就行,因为我们只需要穿两只袜子

我感觉还是挺好想的,但是我看题解里没人发,我就发一份

除了这个思路,其他基本都是模板,不会的话可以来我的博客

或者这个大佬的博客

#include <iostream>
#include <cmath>
#include <algorithm>
 
using namespace std;
 
const int N = 5e4 + 5;
 
struct stu{
    int l,r;
    int id;
    int block;
    bool operator <(const stu &x) const {
        if(x.block == block)
            if(block % 2) return x.r < r;
            else return x.r > r;
        return x.block < block;
    }
        //莫队的普通排序,这样排更优
}q[N];
 
struct find_ans{
    long long son;
    long long mother;
}ans[N];
 
int l,r;
int n,m;
int v[N];
int a[N];
int cnt[N];
long long cur_ans;
long long C[N][4];
 
void init()//预处理组合数
{
    for(int i = 0;i <= n;i ++) C[i][0] = 1;
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= 2;j ++)
            C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
 
}
 
void add(int pos)
{
    cnt[a[pos]] ++;
    int x = cnt[a[pos]];
    cur_ans = cur_ans + C[x][2] - C[x - 1][2];
}
 
void del(int pos)
{
    cnt[a[pos]] --;
    int x = cnt[a[pos]];
    cur_ans = cur_ans + C[x][2] - C[x + 1][2];
}
 
long long gcd_(long long x,long long y)
{
    if(!y) return x;
    return gcd_(y,x % y);
}
 
find_ans ask()
{
    long long this_ans,that_ans;
    this_ans = C[r - l + 1][2];//总的方案数,分母
    that_ans = cur_ans;
    long long gcd = gcd_(this_ans,that_ans);
    this_ans /= gcd;
    that_ans /= gcd;
    find_ans so_ans;
    so_ans.son = that_ans;
    so_ans.mother = this_ans;
    if(!this_ans) so_ans.mother = 1;
    return so_ans; 
}
 
int main()
{
 
//    freopen("8.in","r",stdin);
//    freopen("88.out","w",stdout);
    cin >> n >> m;
    init();
    for(int i = 1;i <= n;i ++) cin >> a[i];
 
    int div = n / sqrt(m);
    for(int i = 1;i <= m;i ++)
    {
        int x,y;
        cin >> x >> y;
        if(x > y) swap(x,y);//这个地方坑死了,数据居然有l > r
        q[i].l = x;
        q[i].r = y;
        q[i].id = i;
        q[i].block = x / div;
        if(x == y)
        {
            ans[i].son = 0;
            ans[i].mother = 1;
            v[i] = 1;
            continue;
        }
    }
    sort(q + 1,q + 1 + m);
 
    l = 1,r = 0; 
    for(int i = 1;i <= m;i ++)
    {
        if(v[q[i].id]) continue;
        while(l < q[i].l) del(l ++);
        while(l > q[i].l) add(-- l);
        while(r < q[i].r) add(++ r);
        while(r > q[i].r) del(r --);
        ans[q[i].id] = ask();
    }
 
    for(int i = 1;i <= m;i ++)
        cout << ans[i].son << "/" << ans[i].mother << endl;
    return 0;
}
posted @ 2020-12-02 14:11  星&夜  阅读(36)  评论(0编辑  收藏  举报