zoukankan      html  css  js  c++  java
  • 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
    ", ans[i]); 
        return 0;
    }
    View Code
  • 相关阅读:
    vue 使用sass 和less
    生命周期函数以及vue的全局注册
    vue-router的简单实现原理
    vue的三种传参方式
    配置router列表
    vue传参二
    Gym 101933E(状态压缩+记忆化搜索)
    Gym 101933 A(dp)
    Gym 101775H(dp)
    Gym 101775 D (思维)
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3262.html
Copyright © 2011-2022 走看看