zoukankan      html  css  js  c++  java
  • B2568 比特集合 树状数组

    啊啊啊,跳题坑死人。抽了一道国集的题,自己瞎编了一个算法,好像过不了而半途而废。转去看题解,发现用二维树状数组维护一下,偏移量我倒是想对了,但是维护的东西和我的完全不一样。还是有很大差距啊。。。

    题解链接

    吐槽一个事,谁能给我讲讲位运算的优先级?

    #include<iostream>
    #include<cstring>
    #include<ctime>
    #include<cmath>
    #include<algorithm>
    #include<iomanip>
    #include<cstdlib>
    #include<cstdio>
    #include<map>
    #include<bitset>
    #include<set>
    #include<stack>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAXN 1010
    #define MAXM 1010
    #define ll long long
    #define eps 1e-8
    #define MOD 1000000007
    #define INF 1000000000
    #define lb(x) x & -x
    int m;
    int N=1<<16;
    char o[MAXN];
    int c[17][1000010];
    int ch;
    map<int,int>h;
    void change(int *c,int x,int y)
    {
        for(; x <= N; x += lb(x))
        {
            c[x] += y;
        }
    }
    int ask(int *c,int x)
    {
        int re=0;
        for(; x; x -= lb(x))
        {
            re += c[x];
        }
        return re;
    }
    int main()
    {
        int i;
        int x;
        scanf("%d",&m);
        while(m--)
        {
            scanf("%s",o);
            if(o[0] == 'I')
            {
                scanf("%d",&x);
                h[x - ch]++; //ch为偏移量
                for(i = 1; i <= 16;i++)
                {
                    change(c[i],(x - ch & ((1 << i) - 1)) + 1,1);//维护树状数组 
                }
            }
            if(o[0] == 'D')
            {
                scanf("%d",&x);
                for(i = 1; i <= 16; i++)
                {
                    change(c[i],(x - ch & ((1 << i) - 1)) + 1,-h[x - ch]);//正常的删除操作 
                }
                h[x - ch] = 0;
            }
            if(o[0] == 'A')
            {
                scanf("%d",&x);
                ch += x;
            }
            if(o[0] == 'Q')
            {
                scanf("%d",&x);
                int ans = 0;
                ans += ask(c[x + 1],min(max((1 << x + 1) - (ch & ((1 << x + 1) - 1)),0),1 << x + 1));
                ans -= ask(c[x + 1],min(max((1 << x) - (ch & ((1 << x + 1) - 1)),0),1 << x + 1));
                //这里最不好理解,前两句是统计没有进位的情况
                //下两句统计进位的情况,有点复杂 
                //这块理解不了可以去链接看一眼 (其实我也不太懂) 
                ans += ask(c[x + 1],min(max((1 << x + 2)-(ch & ((1 << x + 1) - 1)),0),1 << x + 1));
                ans -= ask(c[x + 1],min(max((1 << x) + (1 << x + 1)-(ch & ((1 << x + 1) - 1)),0),1 << x + 1));
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    /*
    8
    INS 1
    QBIT 0
    ADD 1
    QBIT 0
    QBIT 1
    DEL 2
    INS 1
    QBIT 1
    */

    题干:

    Description
      比特集合是一种抽象数据类型(Abstract Data Type) ,其包含一个集合S,并支持如下几种操作:
      INS M : 将元素 M 插入到集合S中;
      DEL M : 将集合S中所有等于 M 的元素删除;
      ADD M : 将集合S中的所有元素都增加数值M ;
      QBIT k : 查询集合中有多少个元素满足其二进制的第 k位为 1 。
      初始时,集合S为空集。请实现一个比特集合,并对于所有的QBIT操作输出相应的答案。
    Input
      输入第一行包含一个正整数N,表示操作的数目。
      接下来N行,每行为一个操作,格式见问题描述。
    Output
      对于每一个QBIT操作,输出一行,表示相应的答案。
    Sample Input
    8
    
    INS 1
    
    QBIT 0
    
    ADD 1
    
    QBIT 0
    
    QBIT 1
    
    DEL 2
    
    INS 1
    
    QBIT 1
    
    Sample Output
    1
    
    0
    
    1
    
    0
    
    HINT
    
    数据规模和约定
    
      时间限制2s。
    
      对于30%的数据,1 ≤ N ≤ 10000。
    
      对于100%的数据,1 ≤ N ≤ 500000;QBIT操作中的k满足, 0 ≤ k < 16。INS/DEL操作中,满足0 ≤ M ≤ 10^9;ADD操作中, 满足0 ≤ M ≤ 1000。
    
    注意
    
      注意集合S可以包含多个重复元素。
    
     
    
    Source
    
    2012国家集训队Round 1 day4

    我的凉凉代码(都没写完):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<map>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    priority_queue <int> qu;
    int cha[20],a[500005];
    int tot[20],n,x,q = 0;
    int k[20];
    char s[10];
    void ins(int x)
    {
        int len = 0,ok = 0;
        clean(k);
        while(x != 0)
        {
            if(x % 2 == 1)
            {
                tot[len]++;
                k[len] = 1;
                if(k[len - 1] == 1)
                cha[len]++;
            }
            x /= 2;
            len++;
        }
    }
    void add(int x)
    {
        q += x;
        
    }
    int main()
    {
        read(n);
        duke(i,1,n)
        {
            scanf("%s",s);
            if(s[0] == 'I')
            {
                read(x);
                ins(x);
                qu.push(x - q);
            }
            else if(s[0] == 'A')
            {
                read(x);
                add(x);
            }
            else if(s[0] == 'D')
            {
                read(x);
                del(x);
            }
            else
            {
                read(x);
                qbit(x);
            }
        }
    }

    正解(不是我写的,但是我改了一下,加了点注释)

  • 相关阅读:
    vue报错 Do not use built-in or reserved HTML elements as component id:header
    vue 报错./lib/html5-entities.js this relative module was not
    vue报错/ style-loader: Adds some css to the DOM by adding a <style> tag
    vue报错 Module not found: Error: Cannot resolve 'file' or 'directory'
    vue报错 vue-cli 引入 stylus 失败
    oracle 定时任务
    Java 基础面试题
    在Java中调用带参数的存储过程
    Linux安装JDK完整步骤
    Spring中获取数据库表主键序列
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9532017.html
Copyright © 2011-2022 走看看