BZOJ4170 极光(CDQ分治 或 树套树)
来源:互联网 发布:淘宝流量钱包流量充值 编辑:程序博客网 时间:2024/05/18 03:49
传送门
BZOJ上的题目没有题面……
【样例输入】
3 5
2 4 3
Query 2 2
Modify 1 3
Query 2 2
Modify 1 2
Query 1 1
【样例输出】
2
3
3
这道题稍微分析一下就知道是求一个一个点曼哈顿距离小于k的的范围内的点的个数(把下标看做x,把值看做y)。然后我们只需要旋转一下坐标轴就变成了和“Mokia”或“简单题”一样的CDQ分治裸题了,求二维空间前缀和。
首先将询问按x排序,然后开始分治过程,计算左半区间对右半区间的贡献,然后就写完了呀!
然后是树套树做法,这个就更Naive了呀,直接套,反正就是求区间前缀和,乱搞搞就A了(不知道为什么对内存的需求不对啊……)。
CDQ版:
#include <cstdio>#include <algorithm>#include <iostream>#include <assert.h>#define LL int#define MAXM 300005#define MAXN 100005using namespace std;int a[MAXN];LL ans[MAXN];inline int Min(int a, int b) { return a < b ? a : b; }struct Querys{ int t, x, y, v, k; Querys(){} Querys(int a, int b, int c, int d, int e):t(a),x(b),y(c),v(d),k(e){} inline bool operator < (const Querys &r) const { if(x == r.x && y == r.y) return t < r.t; else if(x == r.x) return y < r.y; else return x < r.x; }} q[MAXM], nq[MAXM];int n, m, cnt = 0, qn, N;inline void GET(int &n) { char c; n = 0; do c=getchar(); while('0' > c || c > '9'); do n=n*10+c-'0',c=getchar(); while('0' <= c && c <= '9');}namespace BIT { LL t[MAXM]; inline void Add(int x, int v) { for(; x <= N; x += x&-x) t[x] += v; } inline LL Q(int x, LL sum = 0) { for(; x; x -= x&-x) sum += t[x]; return sum; }}void cdq(int L, int R) { if(L >= R) return; using namespace BIT; int mid = (L + R) >> 1, lp = L, rp = mid+1; for(int i = L; i <= R; ++ i) if(q[i].t <= mid && q[i].k == 2) Add(q[i].y, 1); else if(q[i].t > mid && q[i].k != 2) ans[q[i].v] += Q(q[i].y) * q[i].k; for(int i = L; i <= R; ++ i) { if(q[i].t <= mid && q[i].k == 2) Add(q[i].y, -1); if(q[i].t <= mid) nq[lp ++] = q[i]; else nq[rp ++] = q[i]; } for(int i = L; i <= R; ++ i) q[i] = nq[i]; cdq(L, mid); cdq(mid+1, R);}int main() { GET(n); GET(m); N = 300000; for(int i = 1; i <= n; ++ i) { GET(a[i]); q[++ cnt] = Querys(cnt, i + a[i], a[i] - i + 160000, 0, 2); } char op[10]; int u, v; for(int i = 1; i <= m; ++ i) { scanf("%s", op); GET(u); GET(v); if('M' == op[0]) { a[u] = v; q[++ cnt] = Querys(cnt, u + v, v - u + 160000, 0, 2); } else { ++ qn; assert(a[u]-u-v+160000-1 > 0); if(u+a[u]-v-1 > 0) q[++ cnt] = Querys(cnt, (u+a[u]-v-1), Min(a[u]-u+v+160000, N), qn, -1); if(u+a[u]-v-1 > 0) q[++ cnt] = Querys(cnt, (u+a[u]-v-1), Min(a[u]-u-v+160000-1,N), qn, 1); q[++ cnt] = Querys(cnt, (u+a[u]+v), Min(a[u]-u+v+160000,N), qn, 1); q[++ cnt] = Querys(cnt, (u+a[u]+v), Min(a[u]-u-v+160000-1,N), qn, -1); } } sort(q+1, q+cnt+1); cdq(1, cnt); for(int i = 1; i <= qn; ++ i) printf("%d\n", ans[i]); return 0;}
树套树版:
#include <cstdio>#define MAXN 1000005inline void GET(int &n) { char c, f = 1; n = 0; do if((c=getchar()) == '-') f = -1; while('0' > c || c > '9'); do n=n*10+c-'0',c=getchar(); while('0' <= c && c <= '9'); n *= f;}unsigned fix[MAXN * 20], sd = 2333;int key[MAXN * 20], s[MAXN * 20][2], sz[MAXN * 20], rt[MAXN], cnt, n, m, N, a[MAXN], num[MAXN];inline unsigned ran() { return sd = sd * sd + sd^27873; }inline void pushup(int x) { sz[x] = sz[s[x][0]] + sz[s[x][1]] + num[x];}inline void rot(int &x, bool f) { int t = s[x][f]; s[x][f] = s[t][f^1]; s[t][f^1] = x; pushup(x); pushup(t); x = t;}void Insert(int &x, int v) { if(!x) { x = ++ cnt; fix[x] = ran(); num[x] = sz[x] = 1; key[x] = v; return; } if(v == key[x]) { ++ num[x]; pushup(x); return; } bool f = key[x] < v; Insert(s[x][f], v); pushup(x); if(fix[s[x][f]] > fix[x]) rot(x, f);} int u, v, i;int Rank(int x, int v) { if(!x) return 0; if(key[x] < v) return sz[x] - sz[s[x][1]] + Rank(s[x][1], v); else if(key[x] > v) return Rank(s[x][0], v); else return sz[x] - sz[s[x][1]];}void Ins(int x, int v) { for(; x <= N; x += x&-x) Insert(rt[x], v);}int Q(int x, int y) { int sum = 0; for(; x > 0; x -= x&-x) sum += Rank(rt[x], y); return sum;}int main() { GET(n); GET(m); N = 2*n + 100000; for(int i = 1; i <= n; ++ i) { GET(a[i]); Ins(i+a[i], a[i]-i); } char op[10]; for(i = 1; i <= m; ++ i) { scanf("%s", op); GET(u); GET(v); if('M' == op[0]) { a[u] = v; Ins(u+a[u], a[u]-u); } else { int ans = Q((u+a[u]+v), a[u]-u+v) - Q((u+a[u]-v-1), a[u]-u+v) - Q((u+a[u]+v), a[u]-u-v-1) + Q((u+a[u]-v-1), a[u]-u-v-1); printf("%d\n", ans); } } return 0;}
0 0
- BZOJ4170 极光(CDQ分治 或 树套树)
- bzoj4170 极光
- BZOJ4170: 极光
- BZOJ4170: 极光
- BZOJ2989 数列/BZOJ4170 极光
- HDU 5324 Boring Class 树套树 或 CDQ分治
- 时间分治(cdq分治)
- BZOJ4170 极光 [二维线段树]
- [BZOJ]4170: 极光 2989: 数列 CDQ分治+树状数组
- hdu 5324 树套树、cdq分治
- bzoj 3262(cdq分治)
- CDQ分治【分治(真得头疼)
- cdq分治
- cdq分治
- cdq分治
- cdq分治
- 三维偏序 树套树&cdq分治
- CDQ-分治和树套树 的结合小结
- 基础练习 特殊回文数
- Codeforces 626B
- android studio运行编译速度慢的解决方法
- 基础控件
- ZooKeeper架构及简介
- BZOJ4170 极光(CDQ分治 或 树套树)
- 项目3:小试循环---(5)求m!
- Java类加载器
- poj1603(最短路)
- DeepLearning--Part2--Chapter6:Feedforward-Deep-Networks(1)
- BigDecimal使用以及异常处理
- n-1 个数中三个数乘积最大的最小公倍数
- 51nod 1347 旋转字符串
- UIActivityViewController头文件学习