题目链接:hdu 4614
思路:给你一段区间,区间每个点代表每个瓶子,两种状态,有话和无花,题目有两种询问,第一是询问你给你一个起点A和花的数,问你将从点A开始连续地插花直到没有空瓶或者已将插了B只(这里地连续并不是区间连续,而是相对于空瓶子来说地)。让你返回两个数,第一是你插花地第一个位置,第二个是你插花地最后一个位置。第二个查询是,给你A,B,让你先清空这段区间地花,并返回一个num表示你清空了多少只花。
我们可以用1代表空瓶子,0代表已经插了花地瓶子。为什么用1代表空而不是1呢,原因在于第一个询问我们需要知道线段树每段区间中地空瓶子总数,方便查询。
然后是查询插花位置地函数在下面的代码中,很难说,看代码理解吧。
代码:
#include<cstdio> #include<algorithm> using namespace std; #define mid (L + R)/2 #define ls rt*2 #define rs rt*2+1 #define lson ls,L,mid #define rson rs,mid+1,R const int mx = 1e5+5; int tree[mx<<2]; int lazy[mx<<2]; void build(int rt, int L, int R) { lazy[rt] = -1; if(L == R) { tree[rt] = 1; return ; } build(lson); build(rson); tree[rt] = tree[ls] + tree[rs]; } void pushDown(int rt, int L, int R) { if(lazy[rt] != -1){ tree[ls] = lazy[rt]*(mid - L + 1); tree[rs] = lazy[rt]*(R - mid); lazy[ls] = lazy[rs] = lazy[rt]; lazy[rt] = -1; } } void upDate(int rt, int L, int R, int l, int r, int c) { if(l <= L && R <= r){ tree[rt] = c*(R - L + 1); lazy[rt] = c; return ; } pushDown(rt,L,R); if(r <= mid) upDate(lson,l,r,c); else if(l > mid) upDate(rson,l,r,c); else{ upDate(lson,l,mid,c); upDate(rson,mid+1,r,c); } tree[rt] = tree[ls] + tree[rs]; } int query(int rt, int L, int R, int l, int r) { if(r < L || l > R) return 0; if(l <= L && R <= r){ return tree[rt]; } pushDown(rt, L, R); if(r <= mid) return query(lson,l,r); else if(l > mid) return query(rson,l,r); else { return query(lson,l,mid) + query(rson,mid+1,r); } } int find(int rt, int L, int R, int l, int r, int num) { if(L == R) return L; pushDown(rt, L, R); int res = query(lson,l,r); if(res >= num) find(lson,l,r,num); else find(rson,l,r,num-res); } int main() { int t, a, b, c; scanf("%d", &t); while(t--){ int n, m; scanf("%d%d", &n ,&m); build(1,0,n-1); for(int i = 0; i < m; i++){ scanf("%d%d%d",&a, &b, &c); if(a == 1){ int res = query(1,0,n-1,b,n-1); if(res == 0){ printf("Can not put any one.\n"); upDate(1,0,n-1,b,n-1,0); } else{ int l = find(1,0,n-1,b,n-1,1); int r = find(1,0,n-1,b,n-1,min(c,res)); printf("%d %d\n",l,r); upDate(1,0,n-1,l,r,0); } } else if(a == 2){ int res = query(1,0,n-1,b,c); upDate(1,0,n-1,b,c,1); printf("%d\n",c-b+1-res); } } printf("\n"); } return 0; }