1. 程式人生 > >bzoj3262 陌上花開

bzoj3262 陌上花開

cdq分治 思想 tor color 題解 定義 problem stream splay

傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=3262

【題解】

cdq分治。

這題是三維偏序問題。我們先對整體排序,合並相同的,記原來的n為N,剩下的個數為n。

然後對於b排序,把a重新編號為1...n

cdq分治的時候呢,我們定義過程solve(l,r)表示解決p[l...r]的問題。

我們用mid把p[l...r]分成兩個子區間p[l...mid],p[mid+1...r],其中每個子區間的a都屬於這個區間,比如p[l...mid]的a就屬於[l,mid]

並且每個b都單調遞增

然後我們處理前面的操作對於後面的影響。

由於兩個都具有單調性,用類似於two-pointers的思想,掃描一個,另一個單調往上,在樹狀數組上的c位置加值,最後對於每個在樹狀數組上統計即可。

然後撤銷操作,並且繼續分治下去即可。

技術分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7
; # define RG register # define ST static int n, K, ans[M], N; struct pa { int a, b, c, s, ans; pa() {} pa(int a, int b, int c) : a(a), b(b), c(c) {} friend bool operator <(pa a, pa b) { return a.a < b.a || (a.a == b.a && a.b < b.b) || (a.a == b.a && a.b == b.b && a.c < b.c); } friend
bool operator ==(pa a, pa b) { return a.a == b.a && a.b == b.b && a.c == b.c; } }t[M], p[M]; int pn = 0; inline bool cmp(pa a, pa b) { return a.b < b.b || (a.b == b.b && a.c < b.c) || (a.b == b.b && a.a == b.a && a.c < b.c); } struct BIT { int c[M<<1], n; # define lb(x) (x&(-x)) inline void set(int _n) { n = _n; memset(c, 0, sizeof c); } inline void edt(int x, int d) { for (; x<=n; x+=lb(x)) c[x] += d; } inline int sum(int x) { int ret = 0; for (; x; x-=lb(x)) ret += c[x]; return ret; } }T; inline void solve(int l, int r) { if(l == r) { p[l].ans += p[l].s-1; return ; } int mid = l+r>>1, t1n = l-1, t2n = mid; for (int i=l; i<=r; ++i) { if(p[i].a <= mid) t[++t1n] = p[i]; else t[++t2n] = p[i]; } for (int i=l; i<=r; ++i) p[i] = t[i]; int j = l; for (int i=mid+1; i<=r; ++i) { for(; j <= mid && p[j].b <= p[i].b; ++j) T.edt(p[j].c, p[j].s); p[i].ans += T.sum(p[i].c); } for (int i=l; i<j; ++i) T.edt(p[i].c, -p[i].s); solve(l, mid); solve(mid+1, r); } int main() { cin >> n >> K; T.set(K); N = n; for (int i=1; i<=n; ++i) { scanf("%d%d%d", &t[i].a, &t[i].b, &t[i].c); t[i].s = 1; } sort(t+1, t+n+1); p[++pn] = t[1]; for (int i=2; i<=n; ++i) if(!(t[i] == t[i-1])) p[++pn] = t[i]; else p[pn].s ++; n = pn; for (int i=1; i<=n; ++i) p[i].a = i; sort(p+1, p+n+1, cmp); solve(1, n); for (int i=1; i<=n; ++i) ans[p[i].ans] += p[i].s; for (int i=0; i<=N-1; ++i) printf("%d\n", ans[i]); return 0; }
View Code

bzoj3262 陌上花開