• 题解 P6587 【超超的序列 加强】


    (Large exttt{P6587})

    思维题 + 板子题

    这道题目蛮有趣的,但坑有点多,在下面会陈述。

    题意

    不做赘述。

    注意出题人十分恶心地没给 (x),(y),(n) 的关系,请各位注意这点。

    思路

    看似很难维护,区间操作,但是我们可以利用 ( exttt{trie}) 的特性来造一棵不同寻常的线段树。

    对于序列上的数的位置 (i) ,模 (2^x) 后,留下 (x) 位后缀,对比所有 (i)(2^{x-1}) 后留下的后缀,只是增加了第 (x) 位( (0)(1) )。

    因此我们可以把序列按这样构造一棵线段树,每个节点由父亲节点延伸出来,两个子节点的后缀相同,唯一区别最高位是 (0)(1)

    ???这不就是 ( exttt{trie}) 吗 ???

    所以,这道题目的本意就是让你建一棵支持区间修改和查询( exttt{trie}) ,按照线段树1的板子做就好了。

    问题解决。


    然后我WA了30+发

    一定要注意三点:

    • 记得先将 (y)(x) 取模再做

    • (y mod 2^x > n) 此时不做修改,并且询问返回0

    • (y le n) 并且 (2^x > n) 此时返回 (a_y)

    代码

    还有一些细节在代码中

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ls n << 1
    #define rs n << 1 | 1
    #define int long long
    const int N = 5e7;
    inline int read()
    {
        register int s = 0;
        register bool neg = 0;
        register char c = getchar();
        for (; c < '0' || c > '9'; c = getchar())
            neg |= (c == '-');
        for (; c >= '0' && c <= '9'; s = s * 10 + (c ^ 48), c = getchar())
            ;
        return (neg ? -s : s);
    }
    
    int a,b,s[N+10],sum[N+10],lazy[N+10],t[N+10];
    
    inline void up(int n) {
        sum[n]=sum[ls]+sum[rs];
        t[n]=t[ls]+t[rs];//区间长度
    }
    
    inline void down(int n) {
        if(!lazy[n]) return;
        if(t[ls]) sum[ls]+=t[ls]*lazy[n];//注意要判断儿子节点是否存在
        if(t[rs]) sum[rs]+=t[rs]*lazy[n];
        if(t[ls]) lazy[ls]+=lazy[n];
        if(t[rs]) lazy[rs]+=lazy[n];
        lazy[n]=0;
    }
    
    inline void insert(int n,int k,int p,int q) {
        if(!q) {
            t[n]=1;
            sum[n]+=p;
            return;
        }
        if(k&1ll) insert(rs,k>>1ll,p,q-1);
        else insert(ls,k>>1ll,p,q-1);
        up(n);
    }
    
    inline void change(int n,int k,int p,int q) {
        if(!q) {//注意这里,return的关键是q为0,而不是k为0,因为前导0是有意义的
            sum[n]+=p*t[n];
            lazy[n]+=p;
            return;
        }
        down(n);
        if(k&1ll) change(rs,k>>1ll,p,q-1);
        else change(ls,k>>1ll,p,q-1);
        up(n);
    }
    
    inline int query(int n,int k,int q) {
        if(!q) return sum[n];
        down(n);
        if(k&1ll) return query(rs,k>>1ll,q-1);
        else return query(ls,k>>1ll,q-1);
    }
    
    signed main()
    {
        // freopen("in1.in", "r", stdin);
        a=read();
        b=read();
        int mx=ceil(log2(a));
        for(int i=1;i<=a;i++) s[i]=read(),insert(1,i,s[i],mx);
        int x,y,z,lst=0,opt,cnt=0;
        for(int i=1;i<=b;i++) {
            opt=(read()+lst)%2+1;
            if(opt==1) {
                x=read();
                y=read();
                z=read();
                y%=(1ll<<x);
                if(x<=mx) change(1,y,z,x);
                else if(y<=a) change(1,y,z,mx);
            }
            else {
                x=read();
                y=read();
                y%=(1ll<<x);
                if(x<=mx) printf("%lld
    ",lst=query(1,y,x));
                else if(y<=a) printf("%lld
    ",lst=query(1,y,mx));
                else printf("%lld
    ",lst=0);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Tuning 14 Using Oracle Data Storage Structures Efficiently
    Tuning 13 Using oracle blocks Efficiently
    Tuning 12 manage statistics
    Tuning SQL 11
    【TYVJ】1307 联络员(最小生成树)
    【wikioi】1022 覆盖(匈牙利)
    【TYVJ】1338 QQ农场(最大流+最大权闭合图)
    【BZOJ】3038: 上帝造题的七分钟2(线段树+暴力)
    【BZOJ】1087: [SCOI2005]互不侵犯King(状压dp)
    【BZOJ】1041: [HAOI2008]圆上的整点(几何)
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/13925197.html
Copyright © 2020-2023  润新知