码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 6183

时间:2018-08-23 22:08:24      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:nbsp   二维线段树   bre   info   root   efi   矩形   lse   .com   

给出二维平面
$opt1.$ 对点 $(x, y)$ 增减颜色 $c$,
$opt2.$ 询问矩形 $(1, y_1), (x, y_2)$ 内出现过的颜色种数
$x, y <= 1e6, c <= 50$

二维线段树 $hehe$

观察特殊性质每次询问的矩形的左上(下)角都在直线 $x = 1$ 上

假设只有一种颜色
如下平面直角坐标系

技术分享图片

这张图貌似并没有什么用

给出黑色点为插入的点
询问绿色矩形内的颜色种数
因为假设只有 $1$ 种颜色
所以只需判断绿色矩形内是否存在插入的点

显然是存在的

Sol
每次插入一个点 $(x, y)$,把 $x$ 当做 $y$ 的权值,线段树维护每个 $y$ 的最小值
即线段树以纵坐标 $y$ 为下标,维护每个数的最小值
相当于单点修改 $y$ 的值为 $min(w_y, x)$
这也就是询问的矩形左上(下)点的特殊性质所在

这样的话
对每个颜色开一颗线段树(动态开点)
每次查询,枚举颜色,线段树查询区间 $(y_1, y_2)$ 内的最小值 $Min$
如果 $Min <= $ 右上(下)点的横坐标则对答案贡献为 $1$

时间复杂度 $O(50nlogn)$

注意:线段树在查询时,如果当前最小值已经 $<=$ 查询的 $x$ 时,不再进行递归
否则会 $TLE$,可能下面的code写都丑

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
const int N = 1e6 + 10;

#define gc getchar()
inline int read() {
    int x = 0; char c = gc;
    while(c < 0 || c > 9) c = gc;
    while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = gc;
    return x;    
}
#undef gc

int Root[55], Lson[N * 4], Rson[N * 4], Minx[N * 4];
int js_root;

void Clear() {
    js_root = 0;
    memset(Root, 0, sizeof Root);
    memset(Lson, 0, sizeof Lson);
    memset(Rson, 0, sizeof Rson);
    memset(Minx, 0x3f, sizeof Minx);
}

void Poi_G(int l, int r, int &jd, int x, int num) {
    if(!jd) jd = ++ js_root;
    Minx[jd] = min(Minx[jd], num);
    if(l == r) return ;
    int mid = (l + r) >> 1;
    if(x <= mid) Poi_G(l, mid, Lson[jd], x, num);
    else Poi_G(mid + 1, r, Rson[jd], x, num);
}

int Ans;

void Sec_A(int l, int r, int jd, int x, int y, int imp) {
    if(!jd || Ans <= imp) return ;
    if(x <= l && r <= y) {Ans = min(Ans, Minx[jd]); return ;}
    if(l == r) return ;
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_A(l, mid, Lson[jd], x, y, imp);
    if(y > mid)  Sec_A(mid + 1, r, Rson[jd], x, y, imp);
}

int main() {
    int opt;
    memset(Minx, 0x3f, sizeof Minx);
    while(scanf("%d", &opt)) {
        if(opt == 3) break;
        else if(opt == 0) Clear();
        else if(opt == 1) {
            int x = read(), y = read(), c = read();
            Poi_G(1, N - 10, Root[c], y, x);
        } else {
            int x = read(), y_1 = read(), y_2 = read(), Out_Ans(0);
            if(y_1 > y_2) std:: swap(y_1, y_2);
            for(int i = 0; i <= 50; i ++) {
                Ans = Minx[N - 9];
                Sec_A(1, N - 10, Root[i], y_1, y_2, x);
                if(Ans <= x) Out_Ans ++;
            }
            printf("%d\n", Out_Ans);
        }
    }
    return 0;
}

 

hdu 6183

标签:nbsp   二维线段树   bre   info   root   efi   矩形   lse   .com   

原文地址:https://www.cnblogs.com/shandongs1/p/9526277.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!