HDU1556---树状数组 | 线段树 |*

输入n,紧接n行,每行a,b

n个气球,a,b表示从第a到第b个气球涂一次色,输出每个球最终的涂几次色

暴力超时,优化数据结构

1.树状数组

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=10010,MAX=100100;

int n,c[MAX];

int lowbit(int x) {
    //计算2^k
    return x&-x;
}

void update(int x,int val)
{
    //向上更新,使所有包含了x的区间都更新一下
    while(x<=n) {
        c[x]+=val;
        x+=lowbit(x);
    }
}

int Sum(int x)
{
    //向下查询
    int sum=0;
    while(x>0) {
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}

int main()
{
    while(~scanf("%d",&n),n) {
        mes(c,0);
        int a,b;
        FF(i,1,n) {
            scanf("%d%d",&a,&b);
            update(a,1);
            update(b+1,-1);
        }
        F(i,1,n) printf("%d ",Sum(i));
        printf("%d\n",Sum(n));
    }

    return 0;
}

 

2.线段树

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#define Lson left,mid,n<<1
#define Rson mid+1,right,n<<1|1
const int MAX=100001;
const int Max=100000<<2;
int s[Max];
int m;
using namespace std;
typedef struct Node
{
    int left;
    int right;
    int value;
};
Node node[Max];
void build_tree(int left,int right,int n)
{
    node[n].left=left;
    node[n].right=right;
    node[n].value=0;
    if(node[n].left==node[n].right)
    return;
    int mid=(node[n].left+node[n].right)>>1;
    build_tree(Lson);
    build_tree(Rson);
}
void query(int left,int right,int n)
{
    if(node[n].left>=left&&node[n].right<=right)///找到要涂颜色区间,这里很重要,表示用区间后再慢慢回归到子节点上
    {
        node[n].value+=1;
        return;
    }
    int mid=(node[n].left+node[n].right)>>1;
    if(right<=mid)
    query(left,right,n<<1);
    else if(left>mid)
    query(left,right,n<<1|1);
    else
    {
        query(Lson);
        query(Rson);
    }
}
void sum(int n)
{
    if(node[n].left==node[n].right)
    {
        s[m]=node[n].value;
        m+=1;
        return;
    }
    node[n<<1].value+=node[n].value;
    node[n<<1|1].value+=node[n].value;
    sum(n<<1);
    sum(n<<1|1);
}
int main()
{
    int n,i,j,a,b;
    while(scanf("%d",&n)&&n)
    {
        build_tree(1,n,1);
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            query(a,b,1);
        }
        m=0;
        sum(1);
        for(i=0;i<m;i++)
        {
            if(i==m-1)
            printf("%d\n",s[i]);
            else
            printf("%d ",s[i]);
        }
    }
    return 0;
}

 

3.奇技淫巧

从此题discuss中看到

每个气球有两属性

  作为起点的次数st

  作为终点的次数ed

一共享变量sum_st记录到当前点的所有作为染色起点次数和

在进行下一个点前,要先减去此点作为染色终点的次数

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxn 100000+5

struct st_ed
{
    int st;
    int ed;
}p[maxn];

int N;

int main()
{
#ifndef ONLINE_JUDGE
   // freopen("in","r",stdin);
#endif
    int a,b;
    while(scanf("%d",&N) && N)
    {
        memset(p,0,sizeof(p));
        for(int i = 1; i <= N; i++)
        {
            scanf("%d%d",&a,&b);
            p[a].st++;
            p[b].ed++;
        }
        int sum_st = 0, sum_ed = 0;
        for(int i = 1; i <= N; i++)
        {
            if(i!=1)
                printf(" ");
            sum_st += p[i].st;
            printf("%d",sum_st);
            sum_st -= p[i].ed;
        }
        printf("\n");
    }
}

同理

数组离散化?

#include "stdio.h"
int main()
{
    int j,n,i,a,m,b;
    while(scanf("%d",&n),n)
    {
        int c[100001]={0};
        j=n;
        m=0;
        while(j--)
        {
            scanf("%d %d",&a,&b);
            c[a]++;
            c[b+1]--;
        }
        for(i=1;i<n;i++)
        {
            m+=c[i];
            printf("%d ",m);
        }
        printf("%d\n",m+c[n]);
    }
    return 0;
}

 

posted @ 2017-05-16 22:31  kimsimple  阅读(392)  评论(0编辑  收藏  举报