【bzoj4150】[AMPPZ2014]The Staging 线段树
2015-10-22 16:47
417 查看
在舞台上有n个枪手,第i个枪手瞄准了第p[i]个枪手,将于第u[i]秒开枪。一个枪手如果成功开枪,
那么被瞄准的枪手会立刻死亡。
现在给出q次修改操作,请在一开始和每次修改操作后统计出最后存活的枪手个数。
p[i]互不相同,p[i] != i。
首先发现枪手形成若干环。于是可以用线段树维护,一个区间的开头那个人的状态对应结尾的状态,以及存活人数。
其他想法:u[i]折线图中只有下降的区间才有存活的人,不知可否用set。
那么被瞄准的枪手会立刻死亡。
现在给出q次修改操作,请在一开始和每次修改操作后统计出最后存活的枪手个数。
p[i]互不相同,p[i] != i。
首先发现枪手形成若干环。于是可以用线段树维护,一个区间的开头那个人的状态对应结尾的状态,以及存活人数。
其他想法:u[i]折线图中只有下降的区间才有存活的人,不知可否用set。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define Rep(i, x, y) for (int i = x; i <= y; i ++) #define Dwn(i, x, y) for (int i = x; i >= y; i --) #define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex) #define u t[x] #define Lc t[x + x] #define Rc t[x + x + 1] using namespace std; typedef long long LL; const int N = 200005; struct arr { int p[2], q[2], m; } t[N * 8]; // 0 -> alive 1 -> die int n, m, c , l1 , r1 , p , lt, pre , a , pl, s1, tot, n1 , n2 , ql, qr, q, sum , T, ans; bool vis , d ; void Upd(int x) { Rep(i, 0, 1) { u.p[i] = Rc.p[ Lc.p[i] ]; u.q[i] = Lc.q[i] + Rc.q[ Lc.p[i] ]; } u.m = (a[Lc.m] < a[Rc.m]) ? Lc.m : Rc.m; } void Build(int x, int l, int r) { if (l == r) { u.p[0] = 1, u.p[1] = d[l], u.q[0] = 1, u.m = l; return ; } int mid = l + r >> 1; Build(x + x, l, mid), Build(x + x + 1, mid + 1, r); Upd(x); } void Change(int x, int l, int r) { if (l == r) { u.p[1] = d[l], u.m = l; return ; } int mid = l + r >> 1; if (q <= mid) Change (x + x, l, mid); else Change (x + x + 1, mid + 1, r); Upd(x); } void Find(int x, int l, int r) { if (ql > r || qr < l) return ; if (ql <= l && r <= qr) { if (a[pl] > a[u.m]) pl = u.m; return ; } int mid = l + r >> 1; Find(x + x, l, mid), Find(x + x + 1, mid + 1, r); } void Qry(int x, int l, int r) { if (ql > r || qr < l) return ; if (ql <= l && r <= qr) { tot += u.q[s1]; s1 = u.p[s1]; return ; } int mid = l + r >> 1; Qry(x + x, l, mid), Qry(x + x + 1, mid + 1, r); } void Prework() { Rep(i, 1, n) if (!vis[i]) { int j = i; l1[++ m] = lt + 1; do { vis[j] = 1; a[++ lt] = c[j], d[lt + 1] = (c[ p[j] ] < c[j]); pre[ p[j] ] = j; n1[j] = lt, n2[j] = m; j = p[j]; } while (j != i); r1[m] = lt, d[ l1[m] ] = d[lt + 1]; } Build(1, 1, n); Rep(i, 1, m) { pl = l1[i], tot = 0; Rep(j, l1[i], r1[i]) if (a[pl] > a[j]) pl = j; s1 = 0, ql = pl, qr = r1[i], Qry(1, 1, n); ql = l1[i], qr = pl - 1, Qry(1, 1, n); tot -= s1, sum[i] = tot, ans += sum[i]; } printf("%d\n", ans); } int main() { scanf ("%d", &n); Rep(i, 1, n) scanf ("%d", &p[i]); Rep(i, 1, n) scanf ("%d", &c[i]); Prework(); scanf ("%d", &T); while (T --) { int x, y, z; scanf ("%d%d", &x, &y); q = n1[x], a[q] = y, z = n2[x]; c[x] = y; d[q] = c[x] < c[ pre[x] ], d[ n1[ p[x] ] ] = c[ p[x] ] < c[x]; Change(1, 1, n), q = n1[ p[x] ], Change(1, 1, n); ql = l1[z], qr = r1[z], pl = n1[x], Find(1, 1, n); tot = 0, s1 = 0; ql = pl, qr = r1[z], Qry(1, 1, n); ql = l1[z], qr = pl - 1, Qry(1, 1, n); tot -= s1, ans += tot - sum[z]; sum[z] = tot; printf("%d\n", ans); } return 0; }
相关文章推荐
- 探索推荐引擎内部的秘密,第 1 部分: 推荐引擎初探
- Jsp页面生成随机验证码图片
- Hadoop2.6.0 + Spark1.4.0 在Ubuntu14.10环境下的伪分布式集群的搭建(实践可用)
- Windows下使用git push命令的无密码设置
- Ghost - 基于 Node.js 构建的开源博客平台
- tomcat集群
- 使用Arrays.sort()对自定义的entity按指定属性进行排序。
- iOS开发在项目中添加文件夹的步骤
- MySQL和MySQLi的区别
- 节点定义,成员分析,构造方法和add方法实现
- 最大子段和问题
- ios开发系列-准备工作
- git本地创建目录提交远程仓库流程
- 2种实现CXF方法例子
- C++ string 的基本操作(不断更新中)
- 【VBA研究】取整函数的使用
- vb.net 2012 使用prodave6.2
- Win10系统怎么设置开机登录时不显示欢迎使用 Windows10登录时跳过欢迎屏幕的设置方法
- java入门第九天 方法的调用
- Qt enum使用总结