hdu4614Vases and Flowers(线段树+二分)
题目描述:
Vases and Flowers
Problem Description
Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, ..., N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.
题目大意:给一个序列长度的花盆,两种操作,操作1:输入a,k,从a-n中没有放置空花盆中从左到右放置最多k躲花,并返回防止的第一个位置和最后一个位置
操作2:输入a,b,将a-b区间中的所有花清除,并返回清除的个数
思路:操作2很好解决,属于常规线段树操作,操作1需要找到防止的第一个位置和最后一个位置,我们可以用二分的方法不停判断区间的sum来找出来,
大家一定要把代码模块化,一个函数一个功能,不然真的很难debug,我知道二分但是还调了好久,就是因为代码太乱...
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 55000; const int inf = 0x3f3f3f3f; #define ls(x) x<<1 #define rs(x) x<<1|1 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r int last[maxn << 2], tag[maxn << 2]; //剩余位置数量和懒标记 int n, m; void build(int rt, int l, int r) { last[rt] = (r - l + 1); tag[rt] = -1; if (l == r) { return; } int mid = (l + r) >> 1; build(lson); build(rson); } void push_up(int rt) { last[rt] = last[ls(rt)] + last[rs(rt)]; } void push_down(int rt,int l,int r) { if (l == r)return; int m = r - l + 1; if (tag[rt] != -1) {//如果需要下推 last[ls(rt)] = tag[rt] * ((m + 1) / 2); last[rs(rt)] = tag[rt] * (m / 2); tag[ls(rt)] = tag[rt]; tag[rs(rt)] = tag[rt]; tag[rt] = -1; } } int qurrry(int rt, int l, int r, int L, int R) { if (L <= l && r <= R) { return last[rt]; } push_down(rt, l, r); int mid = (l + r) >> 1; int ans = 0; if (L <= mid) { ans += qurrry(lson, L, R); } if (R > mid) { ans += qurrry(rson, L, R); } return ans; } int update(int rt, int l, int r, int L, int R,int f) { if (L <= l && r <= R) { int ans = r - l + 1 - last[rt]; if (f==1) { last[rt] = r - l + 1; tag[rt] =1 ; } else { last[rt] = 0; tag[rt] = 0; } return ans; } push_down(rt, l, r); int mid = (l + r) >> 1; int ans = 0; if (L <= mid) { ans += update(lson, L, R,f); } if (R > mid) { ans += update(rson, L, R,f); } push_up(rt); return ans; } int bin_serch(int x, int num) {//二分查找从x位置开始第num个空位的位置 int l = x, r = n,ans=0; while (l <= r) { int mid = (l + r) >> 1; if (qurrry(1, 1, n, x, mid) >= num) { ans = mid;//x-mid中是满足num个数的,更新ans r = mid - 1; } else { l = mid + 1; } } return ans; } int main() { //freopen("test.txt", "r", stdin); int t; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); build(1, 1, n); int cmd, a, b; while (m--) { scanf("%d", &cmd); if (cmd == 1) { int a, k; scanf("%d%d", &a, &k); a++; int cnt = qurrry(1, 1, n, a, n); if (cnt==0) { printf("Can not put any one.\n"); continue; } int lpos = bin_serch(a, 1); int rpos = bin_serch(a, min(cnt, k)); update(1, 1, n, lpos, rpos, 0); printf("%d %d\n", lpos-1, rpos-1); } else { int a, b; scanf("%d%d", &a, &b); printf("%d\n", update(1, 1, n, a+1, b+1, 1)); } } printf("\n"); } return 0; }
思路: