51Nod-1406-与查询

ACM模版

描述

描述

题解

听说卡了I/O,所以直接上输入输出外挂~~~动态规划,挺巧妙的,复杂度O(nlogn),先将所有数添加到cnt[]中,然后从最大数二进制最高位开始,逐位处理即可。可能有些拧的感觉,自己写几组数据试试就明白了~(≧▽≦)/~啦啦啦。

代码

#include <iostream>
#include <cstdio>
#include <cstring>

#define ll long long
#define clr(a, b) memset(a, b, sizeof(a))

using namespace std;

const int MAXN = 1e6 + 1;

// 1000001: 1111 0100 0010 0100 0001 (20位)

void in(int &res)
{
    //  输入外挂
    res = 0;
    char ch;
    if (ch >= '0' && ch <= '9')
    {
        res = ch - '0';
    }
    while ((ch = getchar()) >= '0' && ch <= '9')
    {
        res = res * 10 + (ch - '0');
    }
}

void out(int a)
{
    //  输出外挂
    if (a < 0)
    {
        putchar('-');
        a = -a;
    }
    if (a >= 10)
    {
        out(a / 10);
    }
    putchar(a % 10 + '0');
}

int cnt[MAXN + 10];

int main()
{
    int n, MAX, x;
    clr(cnt, 0);

    in(n);
    MAX = 0;
    for (int i = 0; i < n; i++)
    {
        in(x), MAX = max(x, MAX);
        cnt[x]++;
    }

    int MAX_DIG = 0;
    int tag = MAX;

    while (tag >>= 1)
    {
        MAX_DIG++;
    }

    for (int j = MAX_DIG; j >= 0 ; j--)
    {
        for (int i = 1; i <= MAX; i++)
        {
            if (i & (1 << j))
            {
                cnt[i - (1 << j)] += cnt[i];
            }
        }
    }
    cnt[0] = n;

    for (int i = 0; i < MAXN; i++)
    {
        out(cnt[i]);
        puts("");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值