题目链接: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. "); 123 else 124 printf("%I64d %I64d ",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 ",sum); 133 } 134 } 135 printf(" "); 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. "); 109 else 110 printf("%d %d ",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 ",ans); 118 } 119 } 120 printf(" "); 121 } 122 return 0; 123 }