HDU 4031 Attack(离线+线段树)
来源:互联网 发布:淘宝发货方式怎么修改 编辑:程序博客网 时间:2024/04/27 21:31
官方题解:线段树,标程是离线算法,按时间建立线段树,然后按区间的先后顺序插进去。
1001就是从1到n依次搞定每个点在那些时间被攻击过,由于每个攻击区间都是连续的,所以那些时间可以靠一个线段树来维护起
————————————————————————————————————————————————————————————
其中一个正解是:离线处理,从1~n的墙按顺序处理答案。然后,可以注意到t最多只有50。
开一棵时间线段树,在我的代码中:
atk[x][i]代表在线段树结点x代表的时间区间中,防御壁一开始有 i 个单位时间的无法防御期,此时走过 x 中的时间,会受到的攻击次数。
empty[x][i]代表在线段树结点x代表的时间区间中,防御壁一开始有 i 个单位时间的无法防御期,此时走过 x 中的时间后,会有的无法防御时间。
PS:还有一种分块的在线做法:http://blog.renren.com/share/240115026/8571592218
#include <cstdio>#include <cstring>#include <algorithm>#include <cstring>#include <vector>using namespace std;const int MAXN = 20010;const int MAXT = MAXN << 2;const int MAXP = 55;struct Node { int pos, op, time; Node() {} Node(int pos, int op, int time): pos(pos), op(op), time(time) {} bool operator < (const Node &rhs) const { return pos < rhs.pos; }};vector<int> qtime[MAXN], qid[MAXN];Node attack[MAXN * 2];int ans[MAXN];int T, n, q, t, ncnt, atime;void init() { for(int i = 0; i <= n; ++i) qtime[i].clear(), qid[i].clear(); memset(ans, -1, q * sizeof(int)); ncnt = atime = 0;}#define ll (x << 1)#define rr (ll | 1)#define mid ((l + r) >> 1)int atk[MAXT][MAXP], empty[MAXT][MAXP];int cnt[MAXN];void update(int x) { for(int i = 0; i < t; ++i) { int t = empty[ll][i]; atk[x][i] = atk[ll][i] + atk[rr][t]; empty[x][i] = empty[rr][t]; }}void build(int x, int l, int r) { if(l == r) { atk[x][0] = empty[x][0] = cnt[l] = 0; for(int i = 1; i < t; ++i) atk[x][i] = 0, empty[x][i] = i - 1; } else { build(ll, l, mid); build(rr, mid + 1, r); update(x); }}void modify(int x, int l, int r, int a, int b) { if(a <= l && r <= b) { atk[x][0] = 0; empty[x][0] = cnt[a] ? t - 1 : 0; for(int i = 1; i < t; ++i) atk[x][i] = cnt[a], empty[x][i] = i - 1; } else { if(a <= mid) modify(ll, l, mid, a, b); if(mid < b) modify(rr, mid + 1, r, a, b); update(x); }}void modify(int pos) { modify(1, 1, atime, pos, pos);}int query(int x, int l, int r, int a, int b, int e) { if(a <= l && r <= b) { return atk[x][e]; } else { int res = query(ll, l, mid, a, b, e); if(mid < b) res += query(rr, mid + 1, r, a, b, empty[ll][e]); return res; }}int query(int pos) { if(pos == 0) return 0; return query(1, 1, atime, 1, pos, 0);}char s[10];int main() { scanf("%d", &T); for(int kase = 1; kase <= T; ++kase) { scanf("%d%d%d", &n, &q, &t); init(); for(int i = 0, a, b; i < q; ++i) { scanf("%s", s); if(strcmp(s, "Attack") == 0) { scanf("%d%d", &a, &b); atime++; attack[ncnt++] = Node(a, 1, atime); attack[ncnt++] = Node(b + 1, -1, atime); } else { scanf("%d", &a); qtime[a].push_back(atime); qid[a].push_back(i); } } sort(attack, attack + ncnt); build(1, 1, atime); int p = 0; for(int i = 1; i <= n; ++i) { while(p < ncnt && attack[p].pos == i) { cnt[attack[p].time] += attack[p].op; modify(attack[p++].time); } for(size_t k = 0; k < qtime[i].size(); ++k) ans[qid[i][k]] = query(qtime[i][k]); } printf("Case %d:\n", kase); for(int i = 0; i < q; ++i) if(ans[i] != -1) printf("%d\n", ans[i]); }}
0 0
- HDU 4031 Attack(离线+线段树)
- 线段树 HDU 4031 attack
- HDU 4031 Attack(11年成都 线段树)
- hdu 4031 Attack(树形结构-线段树)
- hdu 4031 attack 树状数组 线段树 两种做法
- 【线段树II:区间修改+点查询】hdu 4031 Attack
- 【线段树】 HDOJ 4031 Attack
- Hdu 5200 Trees (离线线段树)
- HDU 4417 离线线段树
- HDU 3333 离线线段树
- HDU 3874 离线线段树
- HDU 4417 (离线线段树 || 划分树 )
- HDU 3333 Turing Tree(离线线段树)
- gcd(线段树离线处理)——HDU 4630
- HDU 4288 Coder(线段树+离线处理)
- hdu 5862(离线化+线段树+扫描线)
- [HDU 3333] Turing Tree (线段树+离线算法)
- HDU 4417 Super Mario(离线线段树)
- COM学习笔记(八):流程控制
- 理发师睡眠问题
- 【算法学习笔记】14.暴力求解法03 回溯法01 N皇后和素数环
- Date和Calendar
- 1053. Path of Equal Weight (30)
- HDU 4031 Attack(离线+线段树)
- java下运行jar文件
- 从百度世界大会2014中所看到,所感受到的
- 单选,复选框源码
- UVA 11419 - SAM I AM(二分图匹配+最小点覆盖)
- java.lang.reflect.*
- 1931: Next m prime number
- 黑马程序员21——OC之内存管理(计数器)
- HDU 2100 Lovekey【模拟26进制数相加】