HDU 5618:Jam's problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618

题意:……

思路:和NEUOJ那题一样的。重新写了遍理解了一下,算作处理三维偏序的模板了。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 using namespace std;
 6 #define INF 0x3f3f3f3f
 7 #define N 100010
 8 typedef long long LL;
 9 struct node {
10     int x, y, z, id, f;
11 } p[N], s[N];
12 int ans[N], same[N], bit[N], gap;
13
14 bool cmpx(const node &a, const node &b) { if(a.x != b.x) return a.x < b.x; if(a.y != b.y) return a.y < b.y; return a.z < b.z; }
15 bool cmpy(const node &a, const node &b) { if(a.y != b.y) return a.y < b.y; if(a.x != b.x) return a.x < b.x; return a.z < b.z; }
16 bool cmpid(const node &a, const node &b) { return a.id < b.id; }
17 bool check(node a, node b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
18
19 int lowbit(int x) { return x & (-x); }
20
21 void update(int x, int w) { while(x <= gap) bit[x] += w, x += lowbit(x); }
22
23 int query(int x) { int ans = 0; while(x) ans += bit[x], x -= lowbit(x); return ans; }
24
25 void CDQ(int l, int r) {
26     if(l == r) return ;
27     int m = (l + r) >> 1;
28     CDQ(l, m); CDQ(m + 1, r);
29     int cnt = 0;
30     // 标记是在左边还是右边
31     for(int i = l; i <= r; i++) s[++cnt] = p[i], s[cnt].f = i <= m ? 0 : 1;
32     sort(s + 1, s + 1 + cnt, cmpy);
33     for(int i = 1; i <= cnt; i++)
34         if(!s[i].f) update(s[i].z, 1);
35         else ans[s[i].id] += query(s[i].z);
36     for(int i = 1; i <= cnt; i++)
37         if(!s[i].f) update(s[i].z, -1);
38 }
39
40 int main() {
41     int t, n;
42     scanf("%d", &t);
43     while(t--) {
44         scanf("%d", &n); gap = 0;
45         for(int i = 1; i <= n; i++) {
46             scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].z);
47             p[i].id = i; if(p[i].z > gap) gap = p[i].z;
48         }
49         sort(p + 1, p + 1 + n, cmpx);
50         // 离散化
51         for(int i = 1; i <= n; ) {
52             int j = i + 1;
53             while(j <= n && check(p[j], p[i])) j++;
54             while(i < j) same[p[i++].id] = p[j-1].id;
55         }
56         for(int i = 1; i <= n; i++) p[i].x = i;
57         memset(bit, 0, sizeof(bit));
58         memset(ans, 0, sizeof(ans));
59         CDQ(1, n);
60         sort(p + 1, p + 1 + n, cmpid);
61         for(int i = 1; i <= n; i++) printf("%d\n", ans[same[i]]);
62     }
63     return 0;
64 }

HDU 5618:Jam's problem again(CDQ分治+树状数组处理三维偏序)

时间: 2024-10-10 03:05:37

HDU 5618:Jam's problem again(CDQ分治+树状数组处理三维偏序)的相关文章

HDU - 5324:Boring Class (CDQ分治&amp;树状数组&amp;最小字典序)

题意:给定N个组合,每个组合有a和b,现在求最长序列,满足a不升,b不降. 思路:三位偏序,CDQ分治.   但是没想到怎么输出最小字典序,我好菜啊. 最小字典序: 我们倒序CDQ分治,ans[i]表示倒序的以i为结尾的最长序列,如果当前的ans[i]==目前最大,而且满足序列要求,就输出. #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int max

BZOJ 2683 简单题 cdq分治+树状数组

题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后,二维的数据结构是显然不能过的,于是我们可能会考虑把一维排序之后另一位上数据结构什么的,然而cdq分治却能够很好的体现它的作用. 首先,对于每一个询问求和,显然是x在它左边的并且出现时间在它之前的所有的change对他可能会有影响. 我们按照x第一关键字,y第二关键字,操作第三关键字来排序所有的询问,然后在cdq的时候,每次递归处理左半区间,按照x动态的将y这一列的值加到树状数组里,来更新右半边的所有询问,注意这

XJOI NOIP2015模拟赛Day1 T2 ctps bitset优化 或 排序+cdq分治+树状数组+平衡树

题意: 4维空间中有1个点集A,|A|=n,用(a,b,c,d)表示每个点. 共有m个询问,每次询问输入一个点(a,b,c,d),求最大的S,其中S={p|p∈A且ap<=a,bp<=b,cp<=c,dp<=d},输出|S| 输入格式: 第一行n 接下来n行有n个4维点对 第n+2行有一个数m 再接下来m行每行有一个四维点对,表示每个询问 输出格式: 对于每个询问输出一个数 **方法:**bitset优化 或 排序+cdq分治+树状数组+平衡树 解析: 神题,考场不会,暴力骗40,

【BZOJ4553】[Tjoi2016&amp;Heoi2016]序列 cdq分治+树状数组

[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可.注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1

BZOJ2683: 简单题(CDQ分治 + 树状数组)

BZOJ2683: 简单题(CDQ分治 + 树状数组) 题意: 你有一个\(N*N\)的棋盘,每个格子内有一个整数,初始时的时候全部为\(0\),现在需要维护两种操作: 命令 参数限制 内容 \(1\ x\ y\ A\) \(1\le x,y \le N\),A是正整数 将格子\(x,y\)里的数字加上\(A\) \(2\ x1\ y1\ x2\ y2\) \(1\le x1\le x2\le N,1\le y1\le y2\le N\) 输出\(x1\ y1\ x2\ y2\)这个矩形内的数字

Cideforces 1093E Intersection of Permutations (CDQ分治+树状数组)

---恢复内容开始--- 题意:给你两个数组a和b,a,b都是一个n的全排列:有两种操作:一种是询问区间在数组a的区间[l1,r1]和数组b的区间[l2,r2]出现了多少相同的数字,另一种是交换数组b中x位置和y位置的数字. 思路:我们可以建立数组b对数组a的映射mp,mp[x]表示数组b中x位置的数在数组a中出现的位置,这样问题转化为了带修改的询问一个矩形内点的个数的问题.想法是树套树,但是这题卡常,很多树套树会被卡掉,介于本辣鸡的代码能力,很容易写丑,所以用CDQ分治. 此问题和三维偏序问题

[cdq分治][树状数组] Bzoj P3262 陌上花开

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb. 显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N

HDU 5126 stars cdq分治+树状数组

题目链接:点击打开链接 题意: T个case n个操作 1. (x,y,z) 在三维平面的点上增加1 2.询问区间范围内的权值和. 思路: cdq分治套cdq分治,然后套树状数组即可.. #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #inclu

BZOJ1176---[Balkan2007]Mokia (CDQ分治 + 树状数组)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ第一题,warush了好久.. CDQ分治推荐论文: 1 <从<Cash>谈一类分治算法的应用> 陈丹琦 2 <浅谈数据结构题的几个非经典解法>  许昊然 关于CDQ分治,两种要求:①操作不相互影响  ②可以离线处理 题目描述是有问题的,,初始时 全部为0,不是s 题意:二维平面内,两种操作,1 x y v ,位于(x,y)的值加上v...2 x1,