HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614

题目大意:有n个空花瓶,有两种操作:

     操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B朵花,输出第一个和最后一个插入的花瓶,如果任意花瓶都已经满了不能插花,则输出“Can not put any one.”。

     操作②:给出两个数字A,B,表示清空第A~B个花瓶,并输出清空掉的花朵数目。

解题思路:线段树,关于操作②,很简单弄个sum表示区间空花瓶数,计算时清空掉的花朵数=区间长度-sum。

     关于操作①,有两种解法,第一种就是记录更新每个区间的空花瓶的始末点,这样在插花时可以由此直接获得起点终点。

           第二种,就是乱搞,查找全空区间(都是空花瓶)然后插花,全空区间起点终点的获得就不用说了吧。复杂度真的是玄学(感觉完全算不出来),还以为会超时的,竟然比解法一还快点。。。

解法一:

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #define LC(a) ((a<<1))
  4 #define RC(a) ((a<<1)+1)
  5 #define MID(a,b) ((a+b)>>1)
  6 using namespace std;
  7 typedef long long ll;
  8 const int N = 5e4 + 5;
  9 
 10 struct node {
 11     ll l, r;
 12     ll sum, Start, End, color;//Start是第一个空花瓶位置,End是最后一个空花瓶位置,color=-1,0,1代表初始化,清空,插花 
 13 }tree[N<<2];
 14 
 15 ll leave, Start, sum, End;
 16 void pushup(ll p) {
 17     //维护区间空花瓶数量 
 18     tree[p].sum = tree[LC(p)].sum + tree[RC(p)].sum;
 19     tree[p].color = (tree[LC(p)].color == tree[RC(p)].color ? tree[LC(p)].color : -1);
 20     //维护空花瓶起点和终点 
 21     if (tree[LC(p)].Start != 0)
 22         tree[p].Start = tree[LC(p)].Start;
 23     else if (tree[LC(p)].End != 0)
 24         tree[p].Start = tree[LC(p)].End;
 25     else if (tree[RC(p)].Start != 0)
 26         tree[p].Start = tree[RC(p)].Start;
 27     else if (tree[RC(p)].End != 0)
 28         tree[p].Start = tree[RC(p)].End;
 29     else
 30         tree[p].Start = 0;
 31     tree[p].End = max(max(tree[LC(p)].Start, tree[LC(p)].End), max(tree[RC(p)].Start, tree[RC(p)].End));
 32 }
 33 
 34 void pushdown(ll p) {
 35     if (tree[p].color == 0) {
 36         tree[LC(p)].sum = tree[LC(p)].r - tree[LC(p)].l + 1;
 37         tree[LC(p)].Start = tree[LC(p)].l;
 38         tree[LC(p)].End = tree[LC(p)].r;
 39         tree[RC(p)].sum = tree[RC(p)].r - tree[RC(p)].l + 1;
 40         tree[RC(p)].Start = tree[RC(p)].l;
 41         tree[RC(p)].End = tree[RC(p)].r;
 42         tree[LC(p)].color = tree[RC(p)].color = 0;
 43     }
 44     else if (tree[p].color == 1) {
 45         tree[LC(p)].sum = tree[LC(p)].Start = tree[LC(p)].End = tree[RC(p)].sum = tree[RC(p)].Start = tree[RC(p)].End = 0;
 46         tree[LC(p)].color = tree[RC(p)].color = 1;
 47     }
 48 }
 49  
 50 void build(ll p, ll l, ll r) {
 51     tree[p].l = l;
 52     tree[p].r = r;
 53     tree[p].Start = tree[p].End = 0;
 54     tree[p].sum = 0;
 55     if (l == r) {
 56         tree[p].Start = tree[p].End = l;
 57         tree[p].sum = 1;
 58         tree[p].color = -1;
 59         return;
 60     }
 61     build(LC(p), l, MID(l, r));
 62     build(RC(p), MID(l, r) + 1, r);
 63     pushup(p);
 64 }
 65 //清空 
 66 void update(ll p, ll l, ll r) {
 67     if (r<tree[p].l || l>tree[p].r)
 68         return;
 69     if (l <= tree[p].l&&r >= tree[p].r) {
 70         sum += (tree[p].r - tree[p].l + 1 - tree[p].sum);
 71         tree[p].Start = tree[p].l;
 72         tree[p].End = tree[p].r;
 73         tree[p].sum = tree[p].r - tree[p].l + 1;
 74         tree[p].color = 0;
 75         return;
 76     }
 77     pushdown(p);
 78     update(LC(p), l, r);
 79     update(RC(p), l, r);
 80     pushup(p);
 81 }
 82 //插花 
 83 void query(ll p, ll l, ll r) {
 84     if (r<tree[p].l || l>tree[p].r)
 85         return;
 86     if (leave == 0 || tree[p].sum == 0)
 87         return;
 88     if (l <= tree[p].l&&r >= tree[p].r) {
 89         if (Start == 0)
 90             Start = tree[p].Start;
 91         if (leave >= tree[p].sum) {
 92             leave -= tree[p].sum;
 93             End = max(End, tree[p].End);
 94             tree[p].sum = tree[p].Start = tree[p].End = 0;
 95             tree[p].color = 1;
 96             return;
 97         }
 98     }
 99     pushdown(p);
100     query(LC(p), l, r);
101     query(RC(p), l, r);
102     pushup(p);
103 }
104 int main() {
105     ll q;
106     scanf("%I64d",&q);
107     while (q--) {
108         ll n, m;
109         scanf("%I64d %I64d",&n,&m);
110         build(1, 1, n);
111         while (m--) {
112             ll k;
113             scanf("%I64d",&k);
114             //插花 
115             if (k == 1) {
116                 ll a, f;
117                 scanf("%I64d %I64d",&a,&f);
118                 End = Start = 0;
119                 leave = f;
120                 query(1, a + 1, n);
121                 if (Start == 0)
122                     printf("Can not put any one.\n");
123                 else
124                     printf("%I64d %I64d\n",Start-1,End-1);
125             }
126             //清空 
127             else {
128                 ll a, b;
129                 scanf("%I64d %I64d",&a,&b);
130                 sum = 0;
131                 update(1, a + 1, b + 1);
132                 printf("%I64d\n",sum);
133             }
134         }
135         printf("\n");
136     }
137     return 0;
138 }

解法二:

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<vector>
  7 #include<queue>
  8 #include<set>
  9 #include<map>
 10 #include<string>
 11 #define LC(a) (a<<1)
 12 #define RC(a) (a<<1|1)
 13 #define MID(a,b) ((a+b)>>1)
 14 using namespace std;
 15 typedef long long LL;
 16 const int INF=0x3f3f3f3f;
 17 const int N=5e4+5;
 18 
 19 int ans,x,Start,End,flag;
 20 
 21 struct node{
 22     int sum,l,r;//sum表示空花瓶数 
 23 }tree[4*N];
 24 
 25 void pushdown(int p){
 26     //全满 
 27     if(tree[p].sum==tree[p].r-tree[p].l+1){
 28         tree[LC(p)].sum=tree[LC(p)].r-tree[LC(p)].l+1;
 29         tree[RC(p)].sum=tree[RC(p)].r-tree[RC(p)].l+1;
 30     }
 31     //全空 
 32     else if(tree[p].sum==0)
 33         tree[LC(p)].sum=tree[RC(p)].sum=0;
 34 }
 35 
 36 void pushup(int p){
 37     tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum;
 38 }
 39 
 40 void build(int p,int l,int r){
 41     tree[p].l=l;
 42     tree[p].r=r;
 43     if(l==r){
 44         tree[p].sum=1;
 45         return;
 46     }
 47     build(LC(p),l,MID(l,r));
 48     build(RC(p),MID(l,r)+1,r);
 49     pushup(p);
 50 }
 51 
 52 void update(int p,int l,int r){
 53     if(l>tree[p].r||r<tree[p].l)
 54         return;
 55     if(x<=0)
 56         return;    
 57     if(l<=tree[p].l&&r>=tree[p].r){
 58         if(tree[p].sum==0)
 59             return;
 60         //找到全空区间 
 61         if(x>=tree[p].sum&&tree[p].sum==tree[p].r-tree[p].l+1){
 62             if(flag==0){
 63                 Start=tree[p].l;
 64                 flag++;
 65             }
 66             x-=tree[p].sum;
 67             tree[p].sum=0;    
 68             End=tree[p].r;
 69             return;
 70         }
 71     }
 72     pushdown(p);
 73     update(LC(p),l,r);
 74     update(RC(p),l,r);
 75     pushup(p);
 76 }
 77 
 78 void query(int p,int l,int r){
 79     if(l>tree[p].r||r<tree[p].l)
 80         return;
 81     if(l<=tree[p].l&&r>=tree[p].r){
 82         ans+=tree[p].r-tree[p].l+1-tree[p].sum;
 83         tree[p].sum=tree[p].r-tree[p].l+1;
 84         return;
 85     }
 86     pushdown(p);
 87     query(LC(p),l,r);
 88     query(RC(p),l,r);
 89     pushup(p);
 90 }
 91 
 92 int main(){
 93     int T;
 94     scanf("%d",&T);
 95     while(T--){
 96         int n,q;
 97         scanf("%d%d",&n,&q);
 98         build(1,0,n-1);
 99         while(q--){
100             int op;
101             scanf("%d",&op);
102             if(op==1){
103                 int l;
104                 scanf("%d%d",&l,&x);
105                 flag=0;
106                 update(1,l,n-1);
107                 if(flag==0)
108                     printf("Can not put any one.\n");
109                 else
110                     printf("%d %d\n",Start,End);
111             }
112             else{
113                 int l,r;
114                 scanf("%d%d",&l,&r);
115                 ans=0;
116                 query(1,l,r);
117                 printf("%d\n",ans);
118             } 
119         }
120         printf("\n");
121     }
122     return 0;
123 }

 

posted @ 2017-09-27 21:25  Yeader  阅读(165)  评论(0编辑  收藏  举报