树状数组合集

hdu 4605 Magic Ball Game

树状数组在dfs的应用,比较适合求区间的和
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
#define MAXN 100010
/**
    从1到v的路径固定,按照dfs的思想,等同于只考虑
    一条支路;在一条支路上分为左右部分,找出大于x的
    个数和小于x的个数
*/
int n, m, q;
int w[MAXN], cnt, d[MAXN<<1], res[MAXN<<1][2], ans[MAXN][2];
struct node {int a, b; node(int _a, int _b):a(_a),b(_b){}};
vector<int> son[MAXN];
vector<node> mp[MAXN];
int lowbit(int c)
{
    return c & -c;
}
void update(int u, int c, int val)
{
    for (int i = u; i <= cnt; i += lowbit(i))
        res[i][c] += val;
}
int getSum(int u, int c)
{
    int sum = 0;
    for (int i = u; i > 0; i -= lowbit(i))
        sum += res[i][c];
    return sum;
}
int top, stk[MAXN];
int cson[MAXN], mpot[MAXN];
void dfs()
{
    top = 0;
    stk[top++] = 1;
    memset(cson, 0, sizeof cson);
    int u, i, s;
    int wei, dx, p, la, ra, lb, rb, lc, rc;
    int v, wv;
    while (top)
    {
        u = stk[top-1];
        if (cson[u] == 0)
        {
            s = mp[u].size();
            for (i = 0; i< s; ++i)
            {
                wei = mp[u][i].b;
                dx = mp[u][i].a;
                p = lower_bound(d, d+cnt, wei)-d+1;
                la = getSum(p-1, 0);
                ra = getSum(p-1, 1);
                lb = getSum(cnt, 0);
                rb = getSum(cnt, 1);
                lc = lb - getSum(p, 0);
                rc = rb - getSum(p, 1);
                if (la+ra+lc+rc - lb - rb)
                {
                    ans[dx][1] = -1;
                    continue;
                }
                ans[dx][0] = ra;
                ans[dx][1] = (la+ra)*3 + lc + rc;
            }
        }
        if (son[u].size() == 0)
        {
            top--;
            continue;
        }
        s = cson[u];
        if (s & 0x1)
        {
            update(mpot[u], s>>1, -1);
            s = ++cson[u];
            if (s > 3)
            {
                --top;
                continue;
            }
        }
        v = son[u][s>>1];
        wv = w[u];
        mpot[u] = p = lower_bound(d, d+cnt, wv)-d+1;
        update(p, s>>1, 1);
        stk[top++] = v;
        cson[u]++;
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int t, i;
    int u, a, b, x, v;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        cnt = 0;
        for (i = 0; i<= n; ++i)
        {
            son[i].clear();
        }
        for (i = 1; i<= n; ++i)
        {
            scanf("%d", &w[i]);
            d[cnt++] = w[i];
        }
        scanf("%d", &m);
        for (i = 0; i< m; ++i)
        {
            scanf("%d%d%d", &u, &a, &b);
            son[u].push_back(a);
            son[u].push_back(b);
        }
        scanf("%d", &q);
        for (i = 0; i<= q; ++i) mp[i].clear();
        for (i = 0; i< q; ++i)
        {
            scanf("%d%d", &v, &x);
            mp[v].push_back(node(i, x));
            d[cnt++] = x;
        }
        sort(d, d+cnt);
        cnt = unique(d, d+cnt)-d;
        memset(res, 0, sizeof res);
        dfs();
        for (i = 0; i< q; ++i)
        {
            if (ans[i][1] == -1)
                printf("0\n");
            else
                printf("%d %d\n", ans[i][0], ans[i][1]);
        }
    }
    return 0;
}



hdu 4630 No Pain No Game

树状数组、离散化
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 50005;
int n;
int a[MAXN];
int tree[MAXN], pre[MAXN], res[MAXN];
int lowbit(int i)
{
    return i & (-i);
}
void add(int pos, int val)
{
    while (pos <= n)
    {
        tree[pos] = max(tree[pos], val);
        pos += lowbit(pos);
    }
}
int solve(int i)
{
    int r = 0;
    while (i > 0)
    {
        r = max(r, tree[i]);
        i -= lowbit(i);
    }
    return r;
}
struct node
{
    int idx, l, r;
    bool operator < (const node & e) const
    {
        return l > e.l;
    }
    void getin()
    {
        scanf("%d%d", &l, &r);
    }
}query[MAXN];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        for (int i = 1; i<= n; ++i)
        {
            scanf("%d", a+i);
        }
        int q;
        scanf("%d", &q);
        for (int i = 0; i< q; ++i)
        {
            query[i].getin(); query[i].idx = i;
        }
        sort(query, query+q);
        memset(tree, 0, sizeof tree);
        memset(pre, 0, sizeof pre);
        for (int i = 0, j = n; i< q; )
        {
            for (; j>0 && j >= query[i].l; --j)
            {
                for(int k = 1; k*k <= a[j]; ++k)
                {
                    if (a[j] % k == 0)
                    {
                        if (pre[k])
                        {
                            add(pre[k], k);
                        }
                        pre[k] = j;
                        if (k != a[j]/k)
                        {
                            if (pre[a[j]/k])
                            {
                                add(pre[a[j]/k], a[j]/k);
                            }
                            pre[a[j]/k] = j;
                        }
                    }
                }
            }
            while (i < q && query[i].l > j)
            {
                res[query[i].idx] = solve(query[i].r);
                ++i;
            }
        }
        for (int i = 0; i < q; ++i)
            printf("%d\n", res[i]);
    }
    return 0;
}


hdu 4638 Group

与上一题类似
#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 100005;
int sum[MAXN], a[MAXN];
int ans[MAXN];
int vis[MAXN];
int n, m;
// sum[i] 代表 
struct qy
{
	int s, e, id;
	bool operator < (const qy & v) const
	{
		return s < v.s;
	}	
	void getin(int k) 
	{
		id = k;
		scanf("%d%d", &s, &e);
	}
}q[MAXN];
int lowbit(int i) 
{
	return i &(-i);
}
void add(int i, int val)
{
	while (i<= n)
	{
		sum[i] += val;
		i += lowbit(i);
	}
}
int query(int i)
{
	int num = 0;
	while (i > 0)
	{
		num += sum[i];
		i -= lowbit(i);
	}
	return num;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	int t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d", &n, &m);
		for (int i = 1; i<= n; ++i)
		{
			scanf("%d", a+i);
		}
		memset(sum, 0, sizeof sum);
		memset(vis, 0, sizeof vis);
		for (int i = 1; i<= m; ++i)
		{
			q[i].getin(i);
		}
		sort(q+1, q+1+m);
		int k = m;
		for (int i = n; i>= 1; --i)
		{
			int tp = a[i];
			vis[tp] = i;
			add(i, 1);
			if (vis[tp+1]) add(vis[tp+1], -1);
			if (vis[tp-1]) add(vis[tp-1], -1);
			while (k >= 1 && q[k].s == i)
			{
				ans[q[k].id] = query(q[k].e) - query(i-1);
				k--;
			}
		}
		for (int i = 1; i<= m; ++i)
		{
			printf("%d\n", ans[i]);
		}
	}
	return 0;
}


hdu 4777 Rabbit Kingdom

树状数组求解区间内互质的数个数
#include <cstdio>
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 200010;
int n, m;
int sum[MAXN], isprm[MAXN], prime[MAXN], nprm;
int num[MAXN], cp[MAXN][15], LL[MAXN], RR[MAXN], U[MAXN], O[MAXN], ans[MAXN];
vector<int> mmp[MAXN];
struct _query
{
	int l, r, d;
	bool operator < (const _query & a) const
	{
		return r < a.r;
	}
}query[MAXN];
void getprime()
{
	nprm = 0;
	for (int i = 2; i< 500; ++i)
	{
		if (isprm[i] == 0) prime[nprm++] = i;
		for (int j = 0; j<nprm && i*prime[j] < MAXN; ++j)
		{
			isprm[i*prime[j]] = 1;
			if (i % prime[j] == 0) break;
		}
	}
}
int lowbit(int c){	return c&-c; }
void add(int u, int val)
{
	if (!u) return;
	while (u <= n)
	{
		sum[u] += val;
		u += lowbit(u);
	}
}
int getsum(int u)
{
	int res = 0;
	while (u > 0)
	{
		res += sum[u];
		u -= lowbit(u);
	}
	return res;
}
void dividePrime(int idx)
{
	int tp = num[idx];
	cp[idx][0] = 0;
	for (int i = 0; i< nprm && prime[i]*prime[i]<=tp ; ++i)
	{
		if (tp % prime[i] == 0)
		{
			cp[idx][++cp[idx][0]] = prime[i];
			while (tp % prime[i] == 0) tp/=prime[i];
		}
	}
	if (tp != 1) cp[idx][++cp[idx][0]] = tp;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
	int idx;
	getprime();
	while (scanf("%d%d", &n, &m) && (n+m))
	{
		for (int i = 1; i<= n; ++i) scanf("%d", num+i);
		for (int i = 0; i< m; ++i)
		{
			scanf("%d%d", &query[i].l, &query[i].r);
			query[i].d = i;
		}
		sort(query, query+m);
		memset(sum, 0, sizeof sum);
		for (int i = 1; i<= n; ++i) 
			dividePrime(i), LL[i] = 0, RR[i] = n+1;
		for (int i = 0; i< MAXN; ++i)
			U[i] = 0, O[i] = n+1;		
		for (int i = 1; i<= n; ++i)
		{
			for (int j = 1, k=cp[i][0]; j<= k; ++j)
			{
				LL[i] = max(LL[i], U[cp[i][j]]);
				U[cp[i][j]] = i;
			}
		}
		for (int i = n; i>= 1; --i)
		{
			for (int j = 1, k=cp[i][0]; j<= k; ++j)
			{
				RR[i] = min(RR[i], O[cp[i][j]]);
				O[cp[i][j]] = i;
			}
		}
		for (int i = 1; i<= n; ++i) mmp[i].clear();
		for (int i = 1; i<= n; ++i) mmp[RR[i]].push_back(i);
		idx = 1;
		for (int i = 0; i< m; ++i)
		{
			while (idx <= query[i].r && idx <= n)
			{
				add(LL[idx], 1);
				for (int a, j = 0, k=mmp[idx].size(); j<k; ++j)
				{
					a = mmp[idx][j];
					add(LL[a], -1);
					add(a, 1);
				}
				++idx;
			}
			ans[query[i].d] = getsum(query[i].r) - getsum(query[i].l-1);
			ans[query[i].d] = query[i].r-query[i].l+1 - ans[query[i].d];
		}
		for (int i = 0; i< m; ++i) printf("%d\n", ans[i]);
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值