首页 > 代码库 > HDU - 1556 Color the ball(线段树和树状数组)
HDU - 1556 Color the ball(线段树和树状数组)
题意:n个气球,n个操作(每次给区间[a,b]的气球涂颜色),求最后每个气球被涂颜色的次数。
n可以取到100000,所以如果想for,for的话,就 爆!爆!爆!
1.线段树做法:
一道简单的线段树,做了好久都没做出来,果然自己还是太菜了。。。
创建一棵线段树,把里面的涂色次数对应的值都初始化为0。
更新的时候,找到那个要涂色的区间,涂色次数+1。
询问的时候从上往下找到那个区间,每次把值都递归出来。
1 #define LC(a) ((a<<1)+1) 2 #define RC(a) ((a<<1)+2) 3 #define MID(a,b) ((a+b)>>1) 4 #include <stdio.h> 5 6 struct node{ 7 int l,r; 8 int mid; 9 int val; 10 }; 11 12 const int maxn=111111; 13 node T[maxn*4]; 14 15 void create(int p,int l,int r){ 16 T[p].l=l,T[p].r=r,T[p].mid=MID(l,r),T[p].val=0;//初始化所有的val都为0 17 if(l==r) return ;//如果找到最下面就退出 18 create(LC(p),l,T[p].mid); 19 create(RC(p),T[p].mid+1,r); 20 } 21 22 void update(int p,int l,int r){ 23 if(T[p].l==l&&T[p].r==r){//找到这个节点,+1,递归出口 24 T[p].val++; 25 return ; 26 } 27 if(T[p].l==T[p].r) return ;//没找到这个节点,递归出口,特殊情况的出口 28 if(T[p].mid>=r) update(LC(p),l,r);//往左子树找 29 else if(T[p].mid<l) update(RC(p),l,r);//右子树找 30 else{ //如果是分开的区间,两边都要找 31 update(LC(p),l,T[p].mid); 32 update(RC(p),T[p].mid+1,r); 33 } 34 } 35 36 int query(int p,int l,int r){ 37 if(T[p].l==l&&T[p].r==r) return T[p].val;//如果找到这个区间,就返回。递归,之前的值也都加上来了 38 if(T[p].l==T[p].r) return 0;//特殊情况的出口 39 if(r<=T[p].mid) return query(LC(p),l,r)+T[p].val; 40 else if(l>T[p].mid) return query(RC(p),l,r)+T[p].val; 41 else return query(LC(p),l,T[p].mid)+query(RC(p),T[p].mid+1,r)+T[p].val; 42 } 43 44 int main(){ 45 int n,a,b; 46 while(scanf("%d",&n)!=EOF&&n!=0){ 47 create(0,1,n); 48 for(int i=1;i<=n;i++){ 49 scanf("%d %d",&a,&b); 50 update(0,a,b); 51 } 52 for(int i=1;i<=n;i++){ 53 int sum=query(0,i,i); 54 printf("%d",sum); 55 if(i!=n) printf(" "); 56 } 57 printf("\n"); 58 } 59 return 0; 60 }
2.树状数组做法:
HDU - 1556 Color the ball(线段树和树状数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。