首页 > 代码库 > bzoj3262 陌上花开

bzoj3262 陌上花开

传送门: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 陌上花开