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

codeforces 983D

时间:2018-11-03 23:15:17      阅读:331      评论:0      收藏:0      [点我收藏+]

标签:efi   一个   int   odi   set   codeforce   cin   表示   否则   

这题题意非常清真。
给你一个二维平面,初始颜色为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;
}

codeforces 983D

标签:efi   一个   int   odi   set   codeforce   cin   表示   否则   

原文地址:https://www.cnblogs.com/Yuhuger/p/9902307.html

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