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\n",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);
        }
    }
}

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

 

posted @ 2018-08-24 21:10  DukeLv  阅读(375)  评论(0编辑  收藏  举报