1. 程式人生 > >【CDQ分治+樹狀陣列】HDU 5618 Jam's problem again

【CDQ分治+樹狀陣列】HDU 5618 Jam's problem again

【CDQ分治+樹狀陣列】HDU 5618 Jam’s problem again

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

題意:給n個點,求每一個點的滿足xyz都小於等於它的其他點的個數。

思路:經典的cdq分治+樹狀陣列。 方法就是先按照x從小到大排序, 這樣,x一定滿足後面的大於等於前面的, 這樣我們就可以不用管x了, 然後對y進行cdq分治,使得y滿足關係, 在此基礎上用樹狀陣列順便維護z座標。 但是由於cdq分治每次總是要解決左邊對右邊的影響, 所以在相等時, 每次只更新了右邊的點。 因此預處理一下相等的情況。

#include
<cstdio>
#include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map>
#include<queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; const double PI = acos(-1.0); const double eps = 1e-6; const int mod = 1000000000 + 7; const int INF = 1000000000; const int maxn = 100000 + 10; int T,n,m,bit[maxn],maxd,res[maxn]; struct
node { int x, y, z, id; node(int x=0, int y=0, int z=0, int id=0):x(x),y(y),z(z),id(id) {} }a[maxn],b[maxn]; int sum(int x) { int ans = 0; while(x > 0) { ans += bit[x]; x -= x & -x; } return ans; } void add(int x, int d) { while(x <= maxd) { bit[x] += d; x += x & -x; } } bool cmp1(node a, node b) { if(a.x != b.x) return a.x < b.x; else if(a.y != b.y) return a.y < b.y; else return a.z < b.z; } bool cmp2(node a, node b) { if(a.y != b.y) return a.y < b.y; else return a.id < b.id; } void cdq(int l, int r) { if(l == r) return ; int m = (l + r) >> 1; int cc = 0; for(int i=l;i<=m;i++) b[cc++] = node(0, a[i].y, a[i].z, 0); for(int i=m+1;i<=r;i++) b[cc++] = node(0, a[i].y,a[i].z,a[i].id); sort(b, b+cc, cmp2); for(int i=0;i<cc;i++) { if(b[i].id == 0) { add(b[i].z, 1); } else { res[b[i].id] += sum(b[i].z); } } for(int i=0;i<cc;i++) { if(b[i].id == 0) add(b[i].z, -1); } cdq(l, m); cdq(m+1, r); } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); maxd = 0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); a[i].id = i; maxd = max(maxd, a[i].z); } sort(a+1, a+n+1, cmp1); memset(res, 0, sizeof(int)*(n+5)); int cnt = 0; for(int i=n;i>=1;i--) { if(a[i].x == a[i+1].x && a[i].y == a[i+1].y && a[i].z == a[i+1].z) cnt++; else cnt = 0; res[a[i].id] += cnt; } cdq(1, n); for(int i=1;i<=n;i++) { printf("%d\n",res[i]); } } return 0; }