zoukankan      html  css  js  c++  java
  • codeforces 983D

    这题题意非常清真。
    给你一个二维平面,初始颜色为0,第i操作给一个矩形涂上i颜色,问最后可见颜色数量。
    第一眼感觉是二维线段树,
    但是二维线段树真的可以矩形加,矩形查询并保证复杂度吗???
    我并不会。
    于是前去学习题解。
    题解非常详细:
    1.离线修改,扫描x轴,维护y轴上的线段树
    2.线段树的每个节点维护三个对象,
    第一个是一个set,表示修改时拆到改区间上的颜色集合
    第二个是max,表示最大可见元素(若没有为0)。
    第三个是min,是维护max用的,可以理解为max至少是多少。
    3.重点是pushup
    如果是叶子节点,如果该最大set元素没有出现过,max=max_element(set),min=0,
    否则max=0,min=max_element(set)
    如果是非叶,max对左右孩子取max,min对左右孩子取min(显然,你在左右孩子中任意一个露出来就可以了)
    照例用该节点set最大值没出现过更新max,出现过更新min。
    如果这个节点的max甚至没达到min的标准,那么就没有任何一种新的露出颜色。
    感觉说的很不清楚,还是看代码吧~

    #include <bits/stdc++.h>
    using namespace std;
    const int N=100010;
    const int P=540000;
    set<int> s[P];
    int ll,rr,vv,mx[P],mi[P];
    int a[N],b[N],c[N],d[N];
    bool del[N];
    #define M int mid=(l+r)>>1
    #define L (ind<<1,l,mid)
    #define R (ind<<1|1,mid+1,r)
    void up(int ind,int l,int r){
        if (l^r){
            mx[ind]=max(mx[ind<<1],mx[ind<<1|1]);
            mi[ind]=min(mi[ind<<1],mi[ind<<1|1]);
        }
        else mx[ind]=mi[ind]=0;
        if (s[ind].size()){
            int tmp=*s[ind].rbegin();
            if (del[tmp]) mi[ind]=max(mi[ind],tmp); else mx[ind]=max(mx[ind],tmp);
        }
        if (mx[ind]<mi[ind]) mx[ind]=0;
    }
    void modify(int ind,int l,int r){
        if (ll<=l&&r<=rr){
            if (vv>0){
                s[ind].insert(vv);
            }
            else if (vv<0) s[ind].erase(-vv);
            up(ind,l,r);
            return;
        }
        M;
        if (ll<=mid) modify L;
        if (mid<rr) modify R;
        up(ind,l,r);
    }
    map<int,int> mpx,mpy;
    vector<int> e[N+N];
    int main(){
        ios::sync_with_stdio(0);
        int n; cin>>n;
        for (int i=1; i<=n; ++i){
            cin>>a[i]>>b[i]>>c[i]>>d[i];
            mpx[a[i]]=1;
            mpy[b[i]]=1;
            mpx[c[i]]=1;
            mpy[d[i]]=1;
        }
        int szx=0,szy=0;
        for (map<int,int>::iterator it=mpx.begin(); it!=mpx.end(); ++it){
            it->second=++szx;
        }
        for (map<int,int>::iterator it=mpy.begin(); it!=mpy.end(); ++it){
            it->second=++szy;
        }
        for (int i=1; i<=n; ++i){
            a[i]=mpx[a[i]],b[i]=mpy[b[i]],c[i]=mpx[c[i]],d[i]=mpy[d[i]]-1;
            e[a[i]].push_back(i);
            e[c[i]].push_back(i);
        }
        int ans=1;
        for (int i=1; i<=szx; ++i){
            for (auto j:e[i]){
                ll=b[j]; rr=d[j]; vv=(i==a[j]?j:-j);
                modify(1,1,szy);
            }    
            while (mx[1]){
                ++ans;
                del[mx[1]]=1;
                ll=b[mx[1]]; rr=d[mx[1]]; vv=0;
                modify(1,1,szy);
            }
        }
        cout<<ans;
    }
  • 相关阅读:
    windows下命令行
    利用border画三角形
    正则
    flex布局
    css笔记
    W3C标准
    SEO相关
    左边固定,右边自适应(解决方案)
    容错性测试的测试点
    Charles安装及使用教程
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/9902307.html
Copyright © 2011-2022 走看看