zoukankan      html  css  js  c++  java
  • #6164. 「美团 CodeM 初赛 Round A」数列互质-莫队

    #6164. 「美团 CodeM 初赛 Round A」数列互质

    思路 : 对这个题来言,莫队可以 n*根号n 离线处理出各个数出现个的次数 ,同时可以得到每个次数出现的次数 ,

    但是还要处理有多少 次数 与ki互质 。根据数列的性质,无论这个区间多长,最长也就是 1 - n这个区间 ,所能产生的

    不同的次数 也就是 根号 n 种  例如 长度为28的 数列    1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 7 7 不同的次数 只有 7种 

    数列越长了 这个性质体现的越明显, 原因就是 根据他们的出现的次数求个和 就算他们都按 最小的次数出现的话 1 2 3 4...s 求和为 (1+s)*s/2

    而这个数又不能超过 区间长度 ,所以 这个 s也就在 根号 长度左右。 所以可以放心的进行暴力求解,有插入删除操作,可以数组模拟链表实现。

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 55555
    int n,m,cnt[maxn*2],tong[maxn*2],block,ans[maxn],data[maxn];
    int nxt[maxn*2],lst[maxn*2],head=0,tail=maxn-1,l,r;
    struct node
    {
        int l,r,k,id;
        bool operator <(const node &b)const
        {
            return l/block==b.l/block?r<b.r:l<b.l;
        }
    } a[maxn];
    void upda(int rd)
    {
        if(rd<=head)return;
        nxt[rd]=nxt[head];
        nxt[head]=rd;
        lst[rd]=head;
        lst[nxt[rd]]=rd;
    }
    void rmove(int rd)
    {
        if(rd<=head)return;
        nxt[lst[rd]]=nxt[rd];
        lst[nxt[rd]]=lst[rd];
    }
    void ins(int x)
    {
        if(--tong[cnt[x]]==0)rmove(cnt[x]);
        if(++tong[++cnt[x]]==1)upda(cnt[x]);
    }
    void del(int x)
    {
        if(--tong[cnt[x]]==0)rmove(cnt[x]);
        if(++tong[--cnt[x]]==1)upda(cnt[x]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        block=sqrt(n);
        nxt[0]=tail;
        lst[tail]=0;
        for(int i=1; i<=n; i++)
            scanf("%d",&data[i]);
        for(int i=0; i<m; i++)
        {
            a[i].id=i;
            scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].k);
        }
        sort(a,a+m);
        l=a[0].l;
        r=a[0].l-1;
        for(int i=0; i<m; i++)
        {
            while(l>a[i].l)
                ins(data[--l]);
            while(l<a[i].l)
                del(data[l++]);
            while(r>a[i].r)
                del(data[r--]);
            while(r<a[i].r)
                ins(data[++r]);
            int cp=0;
            for(int j=nxt[head]; j!=tail; j=nxt[j])
                if(__gcd(a[i].k,j)==1) cp+=tong[j];
            ans[a[i].id]=cp;
        }
        for(int i=0; i<m; i++)printf("%d
    ",ans[i]);
        return 0;
    }
    

      

  • 相关阅读:
    Java for LeetCode 229 Majority Element II
    Java for LeetCode 228 Summary Ranges
    Java for LeetCode 227 Basic Calculator II
    Java for LintCode 颜色分类
    Java for LintCode 链表插入排序
    Java for LintCode 颠倒整数
    Java for LintCode 验证二叉查找树
    Java for LeetCode 226 Invert Binary Tree
    Java for LeetCode 225 Implement Stack using Queues
    Java for LeetCode 224 Basic Calculator
  • 原文地址:https://www.cnblogs.com/SDUTNING/p/10239963.html
Copyright © 2011-2022 走看看