BestCoder Round #45

呃。。虽然发挥不咋样但是状态似乎回转了一点。。

1001.Dylans loves numbers

问一个整数n的二进制中有多少组1。

如果两个1之间有若干个(至少一个)0挡住,他们就不是一组的,否则他们就是一组的。

嗯。。直接模拟吧。

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

using namespace std;

int T;
long long n;

int solve() {
    int cnt = 0;
    bool flag = false;
    while (n) {
        if (n & 1) {
            if (!flag) cnt++;
            flag = 1;
        } else flag = 0;
        n >>= 1;
    }
    return cnt;
}

int main() {
    scanf("%d", &T);
    while (T--) {
        cin >> n;
        printf("%d\n", solve());
    }
    return 0;
}

1002.Dylans loves sequence

给你n个数,q个询问,每个询问要求输出[l, r]这些数中逆序对的个数。

因为n<=1000所以直接 n2 枚举i,j求出[i, j]的逆序对个数就可以啦。

逆序对用树状数组维护,这里不再赘述。

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

#define MAXN 1005

using namespace std;

struct Node {
    int val;
    int pos;
    bool operator < (const Node &n) const {
        return val < n.val;
    }
};

int n, q;
int arr[MAXN];
Node temp[MAXN];
int c[MAXN];
int reflect[MAXN];

int lowBit(int i) {
    return i & (-i);
}

void update(int x, int d) {
    while (x <= n) {
        c[x] += d;
        x += lowBit(x);
    }
}

int getSum(int x) {
    int ans = 0;
    while (x > 0) {
        ans += c[x];
        x -= lowBit(x);
    }
    return ans;
}

int ans[1005][1005];
int main() {
    scanf("%d %d", &n, &q);
    for (int i = 1; i <= n; i++)
        scanf("%d", &arr[i]);

    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
            temp[j - i + 1].val = arr[j];
            temp[j - i + 1].pos = j - i + 1;
        }
        stable_sort(temp + 1, temp + n - i + 2);
        for (int j = 1; j <= n - i + 1; j++) {
            reflect[temp[j].pos] = j;
        }
        memset(c, 0, sizeof(c));
        for (int j = 1; j <= n - i + 1; j++) {  
            update(reflect[j], 1);  
            ans[i][j + i - 1] = ans[i][j + i - 2] + j - getSum(reflect[j]);  
        }  
    }
    int a, b;
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        printf("%d\n", ans[a][b]);
    }
    return 0;
}

1003.Dylans loves tree

一棵n个点的树,每个点有点权,树上节点标号1~n。

有q个询问,形式如下:

  1. 0 x y:把第x个点的权值修改为y。
  2. 1 x y:对于x~y路径上的每一种点权,是否都出现奇数次?保证每次询问的路径上最多只有一种点权出现了奇数次。

点权>=0。

对于询问2,因为保证路径上最多只有一种点权出现了奇数次,所以将路径上的值异或起来,如果不为0则该值就是答案。如果为0,有两种可能,一种是所有权值都出现了偶数次,或者权值0出现了奇数次,为了避免这种情况,我们把所有权值都+1,最后输出的时候-1即可。

裸的树剖,然而我这个沙茶调到早上才发现变量忘了初始化。

还有就是别忘了手工栈或者栈外挂。

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <climits>
#include <vector>

#define lch rt << 1
#define rch rt << 1 | 1
#define lson l, mid, lch
#define rson mid + 1, r, rch

using namespace std;

const int MAXN = 100005;

int n, q;
int value[MAXN];
vector<int> edges[MAXN];
int tot = 0;
int siz[MAXN], deep[MAXN], max_son[MAXN];
int mark[MAXN], top[MAXN];
int fa[MAXN];

void dfs_size(int x, int dep) {

    deep[x] = dep;
    max_son[x] = 0;
    siz[x] = 1;

    for (int i = 0; i < edges[x].size(); i++) {
        int nex = edges[x][i];
        if (nex == fa[x]) continue;
        fa[nex] = x;
        dfs_size(nex, dep + 1);

        siz[x] += siz[nex];
        if (!max_son[x] || siz[nex] > siz[max_son[x]])
            max_son[x] = nex;
    }
}

int _num = 0;
void dfs_remark(int x, int topx) {
    top[x] = topx;
    mark[x] = ++_num;
    if (max_son[x]) dfs_remark(max_son[x], topx);
    for (int i = 0; i < edges[x].size(); i++) {
        int nex = edges[x][i];
        if (nex == fa[x]) continue;
        if (max_son[x] != nex)
            dfs_remark(nex, nex);
    }

}

int sum[MAXN << 2];
void push_up(int rt) { sum[rt] = sum[lch] ^ sum[rch]; }
void build_tree(int l, int r, int rt) {
    int mid = l + r >> 1;
    sum[rt] = 0;
    if (l == r) return;
    build_tree(lson);
    build_tree(rson);
}
void insert(int l, int r, int rt, int id, int val) {
    if (l == r) {
        sum[rt] = val;
        return;
    }
    int mid = l + r >> 1;
    if (id <= mid) insert(lson, id, val);
    else insert(rson, id, val);
    push_up(rt);
}

int query(int l, int r, int rt, int L, int R) {
    if (L <= l && R >= r)
        return sum[rt];
    int mid = l + r >> 1;
    int sum = 0;
    if (L <= mid) {
        sum ^= query(lson, L, R);
    }
    if (mid < R) {
        sum ^= query(rson, L, R);
    }
    return sum;
}

int solve(int a, int b) {
    int f1 = top[a], f2 = top[b];
    int ans = 0;
    while (f1 != f2) {
        if (deep[f1] < deep[f2]) {
            swap(f1, f2);
            swap(a, b);
        }
        ans ^= query(1, n, 1, mark[f1], mark[a]);
        a = fa[f1];
        f1 = top[a];
    }
    if (deep[a] > deep[b]) swap(a, b);
    return ans ^ query(1, n, 1, mark[a], mark[b]);
}

int T;
int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d %d", &n, &q);
        int a, b;
        for (int i = 1; i <= n; i++)
            edges[i].clear();
        tot = _num = 0;

        for (int i = 1; i < n; i++) {
            scanf("%d %d", &a, &b);
            edges[a].push_back(b);
            edges[b].push_back(a);
        }
        for (int i = 1; i <= n; i++) {
            scanf("%d", &value[i]);
            value[i]++;
        }
        dfs_size(1, 1);
        dfs_remark(1, 1);
        build_tree(1, n, 1);
        for (int i = 1; i <= n; i++) insert(1, n, 1, mark[i], value[i]);
        int op, x, y;
        for (int i = 0; i < q; i++) {
            scanf("%d", &op);
            scanf("%d %d", &x, &y);
            if (!op) {
                y++;
                insert(1, n, 1, mark[x], y);
            } else {
                int ans = solve(x, y);
                cout << ans - 1 << endl;
            }
        }
    }
    return 0;
}

1004.Dylans loves polynomial

Dylans有N个平面直角坐标系的点对(Xi,Yi)。
同时还有Q个询问。每次的询问给定三个参数(L,R,x)。
他的任务是用L∼R的这些点构成(R−L)阶多项式来拟合这些点。
为了检验他的多项式,他需要把x带入后计算出多项式的值(即y)。
因为这些多项式系数和点对坐标可能都比较大,所有运算都在模1000000007域下进行。
点对的大小和x均为小于等于250000的正整数。且每一个x都互不相同。
2≤N≤3000,1≤Q≤3000。
1≤L,R≤N且R>L

裸的牛顿插值。。

但是如果直接算逆元的话会T,我们发现坐标范围是250000,于是可以先把0~250000的逆元预处理出来,这样就不会T。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>

using namespace std;

const long long MOD = 1000000007;

long long read() {
    long long x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

int n, q;
long long x[3005], y[3005];
long long c[3005][3005];
long long inv[250005];
long long powmod(long long a, long long b) {
    long long ans = 1;
    while (b) {
        if (b & 1) ans = ans * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return ans;
}

void init() {
    for (int i = 0; i <= 250000; i++)
        inv[i] = powmod(i, MOD - 2);
    for (int j = 0; j < n; j++) {
        for (int i = 0; i + j < n; i++) {
            if (!j) c[i][i + j] = y[i];
            else if (x[i + j] > x[i]) c[i][i + j] = (c[i + 1][i + j] - c[i][i + j - 1] + MOD) % MOD * inv[x[i + j] - x[i]] % MOD;
            else c[i][i + j] = (c[i][i + j - 1] - c[i + 1][i + j] + MOD) % MOD * inv[-x[i + j] + x[i]] % MOD;
        }
    }
}

long long calc(int l, int r, long long xx) {
    long long ans = 0, t = 1;
    for (int i = l; i <= r; i++) {
        ans = (ans + c[l][i] * t % MOD) % MOD;
        t = t * (xx - x[i] + MOD) % MOD;
    }
    return ans;
}

int main() {
    n = read();
    for (int i = 0; i < n; i++) {
        x[i] = read();
        y[i] = read();
    }
    init();
    q = read();
    int l, r, xx;
    for (int i = 0; i < q; i++) {
        l = read();
        r = read();
        xx = read();
        printf("%I64d\n", calc(l - 1, r - 1, xx));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值