• 洛谷 P5610 [Ynoi2013] 大学


    一个长为 (n)非负整数序列 (a),支持以下两个操作:

    • 1 l r x:把区间 ([l,r]) 中所有 (x) 的倍数除以 (x)
    • 2 l r:查询区间 ([l,r]) 的和。

    本题强制在线,每次的 (l,r,x) 需要 xor 上上次答案,如果之前没有询问,则上次答案为 (0)

    (1leq n,mleq 10^5)(0leq a_ileq 5 imes 10^5),解密后的 (x,l,r) 满足 (1leq xleq 5 imes 10^5)(1leq lleq rleq n)


    卡常太难了/kk

    发现一个数被操作的次数不会很多,最多操作 (loga_i) 次,那么可以考虑对于每个因数找到他所有倍数的编号,每次询问之后先二分出 (l) 的位置,然后往后暴力删除。单点修改和区间求和用树状数组就可以了。

    但是这样子中间的被除过之后不是 (x) 的倍数会被访问很多次,那么考虑开个并查集,如果一个数被操作之后不是 (x) 的倍数,就把他合并在下一个数的下面。

    因为对每个数的因数都要合并一次,然后要进行 (nloga_i)次修改,所以复杂度是 (O(nd(a_i)alpha(n)+mlognloga_i))

    不过这题太卡常了,所以可以不用vector换用手写内存池。

    但是我还是卡不过去,就给有 (200) 个因子的数的因子打了个表/kk

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #define reg register
    const int N = 1e5;
    const int M = 5e5;
    const int MAXN = 2e7;
    using namespace std;
    int n,m,a[N + 5],pool[MAXN + 5],pool2[MAXN + 5],t[M + 5];
    int *p = pool,*p1 = pool2;
    int *d[M + 5],di[500] = {0,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,20,21,22,24,27,28,30,33,35,36,40,42,44,45,48,54,55,56,60,63,66,70,72,77,80,81,84,88,90,99,105,108,110,112,120,126,132,135,140,144,154,162,165,168,176,180,189,198,210,216,220,231,240,252,264,270,280,297,308,315,324,330,336,360,378,385,396,405,420,432,440,462,495,504,528,540,560,567,594,616,630,648,660,693,720,756,770,792,810,840,880,891,924,945,990,1008,1080,1134,1155,1188,1232,1260,1296,1320,1386,1485,1512,1540,1584,1620,1680,1782,1848,1890,1980,2079,2160,2268,2310,2376,2520,2640,2772,2835,2970,3024,3080,3240,3465,3564,3696,3780,3960,4158,4455,4536,4620,4752,5040,5544,5670,5940,6160,6237,6480,6930,7128,7560,7920,8316,8910,9072,9240,10395,11088,11340,11880,12474,13860,14256,15120,16632,17820,18480,20790,22680,23760,24948,27720,31185,33264,35640,41580,45360,49896,55440,62370,71280,83160,99792,124740,166320,249480,498960};
    struct Bit
    {
        long long c[N + 5];
        inline int lowbit(int x)
        {
            return x & (-x);
        }
        inline void add(int x,int v)
        {
            for (;x <= n;x += lowbit(x))
                c[x] += v;
        }
        inline long long query(int x)
        {
            long long ans = 0;
            for (;x;x -= lowbit(x))
                ans += c[x];
            return ans;
        }
    }c;
    struct Dsu
    {
        int *fa,ts;
        inline void init(int n)
        {
            fa = p;
            p += n;
            for (int i = 0;i < n;i++)
                fa[i] = i;
            ts = n;
        }
        inline int find(int x)
        {
            if (fa[x] == x)
                return x;
            return fa[x] = find(fa[x]);
        }
    }fd[M + 5];
    void prework()
    {
        for (reg int i = 1;i <= M;i++)
            for (reg int j = i + i;j <= M;j += i)
                t[i] += t[j];
        for (reg int i = 1;i <= M;i++)
            if (t[i])
                d[i] = p1,p1 += t[i],t[i] = 0;
        for (reg int i = 1;i <= n;i++)
        {
            c.add(i,a[i]);
            if (a[i] == 498960)
            {
                for (reg int j = 1;j <= 199;j++)
                    d[di[j]][t[di[j]]++] = i;
                continue;
            }
            for (reg int j = 2;j * j <= a[i];j++)
                if (a[i] % j == 0)
                {
                    d[j][t[j]++] = i;
                    if (j * j != a[i])
                        d[a[i] / j][t[a[i] / j]++] = i;
                }
            if (a[i] != 0)
                d[a[i]][t[a[i]]++] = i;
        }
        for (reg int i = 1;i <= M;i++)
            if (t[i])
                fd[i].init(t[i]);
    }
    inline long long read()
    {
    	long long X(0);int w(0);char ch(0);
    	while (!isdigit(ch)) w |= ch == '-',ch = getchar();
    	while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar();
    	return w ? -X : X;
    }
    int main()
    {
        //freopen("data.in","r",stdin);
    	//freopen("a1.out","w",stdout);
        n = read();m = read();
        for (reg int i = 1;i <= n;i++)
            a[i] = read(),t[a[i]]++;
        prework();
        int opt;
        long long ans = 0,l,r,x;
        while (m--)
        {
        	//ans = 0;
            opt = read();l = read() ^ ans;r = read() ^ ans;
            if (opt == 1)
            {
                x = read() ^ ans;
                if (x == 1)
                    continue;
                if (!fd[x].ts)
                    continue;
                int st = lower_bound(d[x],d[x] + t[x],l) - d[x];
                for (reg int i = st;i < fd[x].ts;i++)
                {
                    i = fd[x].find(i);
                    if (d[x][i] > r || i >= fd[x].ts)
                        break;
                    if (a[d[x][i]] % x != 0)
                    {
                        if (i + 1 < fd[x].ts)
                            fd[x].fa[i] = fd[x].find(fd[x].fa[i + 1]);
                        else
                            fd[x].ts--;
                    }
                    else
                    {
                        c.add(d[x][i],a[d[x][i]] / x - a[d[x][i]]);
                        a[d[x][i]] /= x;
                        if (a[d[x][i]] % x != 0)
                        {
                            if (i + 1 < fd[x].ts)
                                fd[x].fa[i] = fd[x].find(fd[x].fa[i + 1]);
                        }
                    }
                }
            }
            else
            {
                ans = c.query(r) - c.query(l - 1);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Windows Server 2008 R2 免费使用 7200天 激活
    ceph部署步骤
    for循环间隔修改(解决把以空格隔开需要把一整行作为整体)
    my_learn
    fiddler-抓包
    基础软件搭建
    【原创】一层Nginx反向代理K8S化部署实践
    【原创】K8S使用ceph-csi持久化存储之CephFS
    【原创】K8S使用ceph-csi持久化存储之RBD
    [原创]自动化部署K8S(v1.10.11)集群
  • 原文地址:https://www.cnblogs.com/sdlang/p/14263720.html
Copyright © 2020-2023  润新知