树状数组练习:HDU 1556,POJ 1195,POJ 3321,POJ 2352

版权声明:但行好事,莫问前程。 https://blog.csdn.net/Li_Hongcheng/article/details/81323295

HDU 1556 Color the ball
/一位树状数组板子题(但c[]已经不是定义上的数组了,但是很常用)

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n;
int c[maxn];
int lowbit(int x)
{
    return x&-x;
}

void update(int pos,int val)
{
    while(pos>0)
    {
        c[pos]+=val;
        pos-=lowbit(pos);
    }
}


int getsum(int num)
{
    int sum=0;
    while(num<=n)
    {
        sum+=c[num];
        num+=lowbit(num);
    }
    return sum;
}


int main()
{
    int a,b;
    while(~scanf("%d",&n)&&n)
    {
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            update(b,1);
            update(a-1,-1);
        }
        for(int i=1;i<n;i++)
        {
           printf("%d ",getsum(i));
        }
        printf("%d\n",getsum(n));
    }
}

POJ 1195 Mobile phones
二维树状数组纯板子题

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

using namespace std;

int ca, s, op;
int c[1100][1100];
void add(int i, int j, int v)
{
    while(i <= s)
    {
        int y = j;
        while(y <= s)
        {
            c[i][y] += v;
            y += y&-y;
        }
        i += i&-i;
    }
}
int query(int i,int j)
{
    int ans = 0;
    while(i > 0)
    {
        int y = j;
        while(y > 0)
        {
            ans += c[i][y];
            y -= y&-y;
        }
        i -= i&-i;
    }
    return ans;
}
int main()
{
    cin >> ca >> s;
    while(1)
    {
        scanf("%d", &op);
        if(op == 1)
        {
            int a, b, v;
            scanf("%d%d%d", &a, &b, &v);
            add(a+1, b+1, v);
        }
        else if(op == 2)
        {
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            int ans = query(x2+1, y2+1) + query(x1, y1) - query(x2+1, y1) - query(x1, y2+1);
            printf("%d\n", ans);
        }
        else break;
    }

}

POJ 3321
题意:
给出一个苹果树,每个节点一开始都有苹果
C X,如果X点有苹果,则拿掉,如果没有,则新长出一个
Q X,查询X点与它的所有后代分支一共有几个苹果

用到了dfs序,第一次学。
复制一下大佬们的思路:
思路很巧妙,我们通过自己来编号所有苹果,每个节点保存两个值,左值为本身,右值为其包含的所有后代中最大的编号
我们可以通过搜索来进行编号,在编好号之后,我们可以知道,对于某一点而言,我们是先通过这个点搜完所有他的后代编号才结束的,所以这个点的右值,包含了当前点所有的后代与祖先,后代必然是所有编号大于本节点的点,那么祖先呢,那必然是编号小于这个节点的点了
所以我们通过sum(rig[x])-sum(lef[x]-1)就能得到查询的答案
至于更新,只需要更新当前点即可,这样就转化为树状数组了

#include<stdio.h>
#include<string.h>
#include<cstring>
using namespace std;
const int maxn=210100;
struct node
{
    int to;
    int next;
}e[maxn];
char s;int x;
int in[maxn],out[maxn],c[maxn],cnt=0;
int n,m,tot=0,head[maxn],vis[maxn];
void edd_edge(int u,int v)
{
    tot++;
    e[tot].to=v;
    e[tot].next=head[u];
    head[u]=tot;
}
int lowbit(int x)
{
    return x&(-x);
}
void dfs(int x)
{
    in[x]=++cnt;
    for(int i=head[x];i;i=e[i].next)
    dfs(e[i].to);
    out[x]=cnt;
}
void update(int x,int add)
{
    while(x<=n)
    {
        c[x]+=add;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int s=0;
    while(x>0)
    {
        s+=c[x];
        x-=lowbit(x);
    }
    return s;
}
int main()
{
    int a,b;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        edd_edge(a,b);
    }
    dfs(1);
    for(int i=1;i<=n;i++)
    update(in[i],1),vis[i]=1;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s%d",&s,&x);
        if(s=='C')
        {
            if(vis[x])update(in[x],-1);
            else update(in[x],1);
            vis[x]=1-vis[x];
        }
        if(s=='Q')
       printf("%d\n",sum(out[x])-sum(in[x]-1));
    }
    return 0;
}

题意:

在坐标上有n个星星,如果某个星星坐标为(x, y), 它的左下位置为:(x0,y0),x0<=x 且y0<=y。如果左下位置有a个星星,就表示这个星星属于level x,按照y递增,如果y相同则x递增的顺序给出n个星星,求出所有level水平的数量。

思路:
因为输入是按照按照y递增,如果y相同则x递增的顺序给出的, 所以,对于第i颗星星,它的level就是之前出现过的星星中,横坐标x小于等于i星横坐标的那些星星的总数量(前面的y一定比后面的y小)。所以,需要找到一种数据结构来记录所有星星的x值,方便的求出所有值为0~x的星星总数量。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 32005

int c[maxn];
int levels[maxn];

int lowbit(int x)
{
    return x&(-x);
}

int sum(int x)
{
    int res=0;
    while(x>0)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}

void update(int pos)
{
    while(pos<=32001)
    {
        c[pos]++;
        pos+=lowbit(pos);
    }
}
int main()
{
    int n,x,y;
    while(~scanf("%d",&n))
    {
        memset(levels,0,sizeof(levels));
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&x,&y);
            levels[sum(x+1)]++;
            update(x+1);
        }
        for(int i=0; i<n; i++) 
            printf("%d\n",levels[i]);
    }
}

猜你喜欢

转载自blog.csdn.net/Li_Hongcheng/article/details/81323295
今日推荐