您的位置:首页 > 其它

HDU 4614 Vases and Flowers(线段树、二分)

2016-03-01 01:50 525 查看
题意:

N≤5×104个花瓶,M≤5×104次操作

1 i k:从i开始放k束花,如果i放过了,就i+1,依次类推,插够为止,多了的丢弃

输出插花的第一个位置和最后一个位置,不能就是输出Can not put any one.

2 l r:把[l,r]放过花的位置空出来,输出空出了几个

分析:

线段树维护剩余空花瓶的个数

第一种操作二分≥1的最左边的位置,二分≥k的最左边位置

第二种直接更新就好啦

复杂度是O(n+mlog2n)

代码:

//
//  Created by TaoSama on 2016-02-28
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, q;

struct SegTree {
int sum[N << 1], lazy[N << 1];
void build(int l, int r, int rt) {
sum[rt] = r - l + 1;
lazy[rt] = -1;
if(l == r) return;
int m = l + r >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
}
void pushUp(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void pushDown(int rt, int m) {
if(~lazy[rt]) {
sum[rt << 1] = lazy[rt] * (m - (m >> 1));
sum[rt << 1 | 1] = lazy[rt] * (m >> 1);
lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
lazy[rt] = -1;
}
}
int update(int L, int R, int v, int l, int r, int rt) {
if(L <= l && r <= R) {
int ret = sum[rt];
sum[rt] = v * (r - l + 1);
lazy[rt] = v;
return ret;
}
int m = l + r >> 1, ret = 0;
pushDown(rt, r - l + 1);
if(L <= m) ret += update(L, R, v, l, m, rt << 1);
if(R > m) ret += update(L, R, v, m + 1, r, rt << 1 | 1);
pushUp(rt);
return ret;
}
int query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) return sum[rt];
int m = l + r >> 1, ret = 0;
pushDown(rt, r - l + 1);
if(L <= m) ret += query(L, R, l, m, rt << 1);
if(R > m) ret += query(L, R, m + 1, r, rt << 1 | 1);
return ret;
}
} T;

int get(int st, int k) {
int l = st, r = n;
while(l <= r) {
int m = l + r >> 1;
if(T.query(st, m, 1, n, 1) >= k)  r = m - 1;
else l = m + 1;
}
return l == n + 1 ? -1 : l;
}

int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &q);
T.build(1, n, 1);
while(q--) {
int op, x, y; scanf("%d%d%d", &op, &x, &y);
if(op == 1) {
int all = T.query(x + 1, n, 1, n, 1);
if(all == 0) {
puts("Can not put any one.");
} else {
int l = get(x + 1, 1), r = get(x + 1, min(all, y));
T.update(l, r, 0, 1, n, 1);
printf("%d %d\n", l - 1, r - 1);
}
} else {
int tmp = T.update(x + 1, y + 1, 1, 1, n, 1);
int ans = y - x + 1 - tmp;
printf("%d\n", ans);
}
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 二分