hdu 1556 Color the ball 线段树,树状树组,与dp思想的树组解决技巧

来源:互联网 发布:protel99se软件下载 编辑:程序博客网 时间:2024/06/15 00:51

 来源: http://acm.hdu.edu.cn/showproblem.php?pid=1556;

Color the ball

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5813    Accepted Submission(s): 3099


Problem Description
N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?
 

Input
每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N)。
当N = 0,输入结束。
 

Output
每个测试实例输出一行,包括N个整数,第I个数代表第I个气球总共被涂色的次数。
 

Sample Input
31 12 23 331 11 21 30
 

Sample Output
1 1 13 2 1这个题目在我们学校(ecjtu)比赛时没做出来,因为当时只学会了线段树单点更新与区间求和。后来赛后连续做了两天的线段树,,,线段树水很深,我至今都还有很多技巧没有掌握,大家好好努力吧。首先来看线段树代码:
#include<iostream>#include<cstdio>#include<cstring>#define mem(str,x)  memset(str,(x),sizeof(str))#define mid (l+r)>>1#define len (r-l+1)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int maxn=100010;int sum[maxn<<2],root[maxn<<2],n;inline void pushup(int rt){   sum[rt] = sum[rt<<1] + sum[rt<<1|1];}inline void pushdown(int rt,int _len){    if(root[rt]){        int l=rt<<1,r=rt<<1|1,m=_len>>1;        root[l] += root[rt];        root[r] += root[rt];        sum[l]  += (_len-m)*root[rt];        sum[r]  +=m*root[rt];        root[rt] = 0;    }}void update(int left,int right,int l,int r,int rt){    if(left<=l && right>=r){        ++root[rt];        sum[rt] += len;        return ;    }    pushdown(rt,len);    int m = mid;    if(left<=m) update(left,right,lson);    if(right>m) update(left,right,rson);    pushup(rt);}int query(int left,int right,int l,int r,int rt){    if(left==l && right==r) return sum[rt];    int m = mid;    pushdown(rt,len);    int s;    if(left<=m) s=query(left,right,lson);    else if(right>m) s=query(left,right,rson);    else s=(query(left,m,lson)+query(m+1,right,rson));  return s;}int  main(){    int a,b;    while(~scanf("%d",&n)&&n){        mem(sum,0);mem(root,0);///相当于建树的初始化。        for(int i=0;i<n;i++){            scanf("%d%d",&a,&b);            update(a,b,1,n,1);        }        for(int i=1;i<=n;i++){            printf("%d%c",query(i,i,1,n,1),i==n?'\n':' ');        }    }    return 0;}


下面是树状树组的代码:
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;#define maxn 100000+10int s[maxn];int lowbit(int x){    return x&(-x);}void update(int x,int c,int n){    while(x<=n){        s[x]+=c;        x+=lowbit(x);    }}int getsum(int x){    int sum=0;    while(x>0){            sum+=s[x];            x-=lowbit(x);    }    return sum;}int main(){    int N;    while(scanf("%d",&N),N)    {        memset(s,0,sizeof(s));        for(int i=1;i<=N;i++)        {            int a,b;            scanf("%d%d",&a,&b);            update(a,1,N);            update(b+1,-1,N);        }        for(int i=1;i<=N;i++){            printf("%d%c",getsum(i),i==N?'\n':' ');        }    }    return 0;}

下面是数组解决法(用到了dp思想):
#include<iostream>#include<cstring>#include<cstdio>using namespace  std;#define maxn 100000+10int s[maxn];int main(){    int N;    while(scanf("%d",&N),N){            memset(s,0,sizeof(s));       for(int i=1;i<=N;i++){        int a,b;        scanf("%d%d",&a,&b);        s[a]++;        s[b+1]--;       }       for(int i=1;i<=N;i++){        s[i]+=s[i-1];        printf("%d%c",s[i],i==N?'\n':' ');       }    }    return 0;}





 
原创粉丝点击