• bzoj4418 [Shoi2013]扇形面积并


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4418

    【题解】

    被题目名称吓死系列。

    用一棵线段树维护当前有哪些半径。

    那么将扇形差分,每段空白区域相当于查询线段树内第K大。

    权值线段树就行啦!

    O(nlogn)

    # 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, m, K;
    
    struct pa {
        int r, pos;
        int f;
        pa() {}
        pa(int r, int pos, int f) : r(r), pos(pos), f(f) {}
        friend bool operator <(pa a, pa b) {
            return a.pos < b.pos;
        }
    }p[M]; int pn = 0;
    
    namespace SMT {
        int sz[M];
        # define ls (x<<1)
        # define rs (x<<1|1)
        inline void edt(int x, int l, int r, int pos, int del) {
            if(l == r) {
                sz[x] += del;
                return ;
            }
            int mid = l+r>>1;
            if(pos <= mid) edt(ls, l, mid, pos, del);
            else edt(rs, mid+1, r, pos, del);
            sz[x] = sz[ls] + sz[rs];
        }
        inline int query(int x, int l, int r, int rk) {
            if(l == r) return l;
            int mid = l+r>>1;
            if(sz[rs] < rk) return query(ls, l, mid, rk-sz[rs]);
            else return query(rs, mid+1, r, rk);
        }
        inline int query(int rk) {
            if(sz[1] < rk) return 0;
            else return query(1, 1, 1e5, rk);
        }    
    }
    
    int main() {
        cin >> n >> m >> K;
        for (int i=1, r, a1, a2; i<=n; ++i) {
            scanf("%d%d%d", &r, &a1, &a2);
            p[++pn] = pa(r, a1, 1);
            p[++pn] = pa(r, a2, -1);
            if(a1 > a2) {
                p[++pn] = pa(r, -m, 1);
                p[++pn] = pa(r, m, -1);
            }
        }
        ll ans = 0;
        int lst = -1e9;
        sort(p+1, p+pn+1);
    //    for (int i=1; i<=pn; ++i) printf("pos = %d, r = %d, del = %d
    ", p[i].pos, p[i].r, p[i].f);
        for (int i=1; i<=pn; ++i) {
            int ps = p[i].pos, j=i;
            if(lst != -1e9) {
                int R = SMT::query(K);// cout << p[i].pos << ' ' << R << endl;
                ans += 1ll * R * R * (p[i].pos - lst);
            }
            while(j+1 <= pn && p[j+1].pos == p[i].pos) ++j;
            for (int k=i; k<=j; ++k)
                SMT::edt(1, 1, 1e5, p[k].r, p[k].f);
            lst = p[i].pos;
            i = j;    
        }
        cout << ans;
        return 0;
    }
    View Code
  • 相关阅读:
    密码保护
    实现搜索功能
    完成个人中心—导航标签
    个人中心标签页导航
    评论列表显示及排序,个人中心显示
    完成评论功能
    从首页问答标题到问答详情页
    首页列表显示全部问答,完成问答详情页布局
    Android基础学习:Android环境搭建
    liunx 硬盘分区
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj4418.html
Copyright © 2020-2023  润新知