• 2020/8/9 模拟赛 T3 表格


    Description

    蒟蒻的YHN在用表格(excel)整理题目。它的任务是把所有的题目按照难度, 涂上不同的颜色。红色代表恶心题,黄色代表中档题,绿色代表YHN出的水题。 终于,这枯燥乏味的工作把YHN逼疯了。它疯狂地选中表格中的一些矩形,并同 时给它们涂上某种颜色……当它恢复理智时,表格页面已经变得混乱不堪。 当YHN不停地按Ctrl+Z时,突然想知道,屏幕上能看到多少种颜色? 方便起见,认为所有矩形的颜色互不相同。且整个表格大小为无限大。空位置 为白色(与所有矩形颜色均不同)

    Solution

    这毒瘤题目毁我青春

    用扫描线从左向右扫,维护每次扫到的地方有哪些颜色是第一次看见,更新标记数组,毒瘤就在这维护上

    对于线段树上每个区间维护:区间上能看到的颜色最小值,区间上能看到的且第一次看到的颜色最大值,以及区间上能看见和已被覆盖的完全覆盖整个区间的所有颜色(区间里的所有完全覆盖区间的颜色)

    对于区间上能看到的颜色的最小值,可能是两个子区间上能看到的颜色的最小值的最小值,也可能是区间里所有完全覆盖区间的颜色的最大值,在以上两者之间取最大值,因为颜色大的会覆盖颜色小的,假如有大的颜色覆盖整个区间,就相当于其它小的颜色全部被覆盖

    对于区间上能看到的且第一次看到的颜色最大值,可能是两个子区间上能看到的且第一次看到的颜色的最大值的最大值,也可能是区间里所有完全覆盖区间的颜色的最大值,在以上两者之间取最大值,取最大值的原因同上,注意当区间里所有完全覆盖区间的颜色的最大值小于两子区间上能看到的颜色的最小值的最小值时,说明区间上所有颜色已经被更新,否则,当区间上能看到的且第一次看到的颜色最大值小于区间里所有完全覆盖区间的颜色的最大值时,区间上能看到的且第一次看到的颜色的最大值改为区间里所有完全覆盖区间的颜色的最大值

    每次扫描线移动时将线段树根节点的能看到的且第一次看到的颜色的最大值更新,更新该颜色在线段树上对应的区域的所有标记,直至不能更新,扫描线继续移动

    对于每个颜色都只会被更新$2$次,用set维护区间里的所有完全覆盖区间的颜色,时间复杂度$O(nlog_{n}^2)$

    #pragma GCC optimize(3)
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<set>
    using namespace std;
    int n,xx[200005],yy[200005],cnt1,cnt2,tot,ll[200005],rr[200005],las=1,ans,tcnt;
    bool vst[200005];
    struct Node
    {
        int l,r,x,tag,id;
        bool operator < (const Node &z)const
        {
            if(x==z.x)
            {
                return l<z.l;
            }
            return x<z.x;
        }
    }node[200005];
    struct Tree
    {
        int maxx,minn;
        set<int>s;
    }tree[800020];
    inline int read()
    {
        int w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return w*f;
    }
    void build(int i,int l,int r)
    {
        tree[i].maxx=tree[i].minn=-1;
        if(l==r)
        {
            return;
        }
        int mid=l+r>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
    }
    inline void pushup(int i,int l,int r)
    {
        if(l==r)
        {
            if(tree[i].s.empty())
            {
                tree[i].maxx=tree[i].minn=-1;
                return;
            }
            tree[i].maxx=tree[i].minn=*tree[i].s.rbegin();
            if(vst[tree[i].maxx])
            {
                tree[i].maxx=-1;
            }
        }
        else
        {
            tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);
            tree[i].maxx=max(tree[i<<1].maxx,tree[i<<1|1].maxx);
            if(tree[i].s.empty())
            {
                return;
            }
            tree[i].minn=max(tree[i].minn,*tree[i].s.rbegin());
            if(tree[i].maxx<*tree[i].s.rbegin())
            {
                if(vst[*tree[i].s.rbegin()])
                {
                    tree[i].maxx=-1;
                }
                else
                {
                    if(*tree[i].s.rbegin()<tree[i].minn)
                    {
                        tree[i].maxx=-1;
                    }
                    else
                    {
                        tree[i].maxx=*tree[i].s.rbegin();
                    }
                }
            }
        }
    }
    void update(int i,int l,int r,int L,int R,int val,int f)
    {
        if(L<=l&&r<=R)
        {
            if(f==1)
            {
                tree[i].s.insert(val);
            }
            else
            {
                tree[i].s.erase(val);
            }
            pushup(i,l,r);
            return;
        }
        int mid=l+r>>1;
        if(L<=mid)
        {
            update(i<<1,l,mid,L,R,val,f);
        }
        if(R>mid)
        {
            update(i<<1|1,mid+1,r,L,R,val,f);
        }
        pushup(i,l,r);
    }
    void Push(int i,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)
        {
            pushup(i,l,r);
            return;
        }
        int mid=l+r>>1;
        if(L<=mid)
        {
            Push(i<<1,l,mid,L,R);
        }
        if(R>mid)
        {
            Push(i<<1|1,mid+1,r,L,R);
        }
        pushup(i,l,r);
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            int xa=read(),ya=read(),xb=read(),yb=read();
            node[++tot]=(Node){ya,yb-1,xa,1,i};
            node[++tot]=(Node){ya,yb-1,xb,-1,i};
            xx[++cnt1]=xa;
            xx[++cnt1]=xb;
            yy[++cnt2]=ya;
            yy[++cnt2]=yb-1;
        }
        sort(xx+1,xx+1+cnt1);
        sort(yy+1,yy+1+cnt2);
        cnt1=unique(xx+1,xx+1+cnt1)-xx-1;
        cnt2=unique(yy+1,yy+1+cnt2)-yy-1;
        for(int i=1;i<=tot;i++)
        {
            node[i].l=lower_bound(yy+1,yy+cnt2+1,node[i].l)-yy;
            node[i].r=lower_bound(yy+1,yy+1+cnt2,node[i].r)-yy;
            node[i].x=lower_bound(xx+1,xx+cnt1+1,node[i].x)-xx;
        }
        for(int i=1;i<=tot;i++)
        {
            ll[node[i].id]=node[i].l;
            rr[node[i].id]=node[i].r;
        }
        sort(node+1,node+tot+1);
        build(1,1,cnt2);
        for(int i=1;i<=cnt1;i++)
        {
            while(las<=tot&&node[las].x==i)
            {
                update(1,1,cnt2,node[las].l,node[las].r,node[las].id,node[las].tag);
                ++las;
            }
            while(tree[1].maxx!=-1)
            {
                vst[tree[1].maxx]=true;
                Push(1,1,cnt2,ll[tree[1].maxx],rr[tree[1].maxx]);
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(vst[i])
            {
                ans++;
            }
        }
        printf("%d
    ",ans+1);
        return 0;
    }
    表格
  • 相关阅读:
    计算机专业,刚刚大一,该如何学好程序设计?
    打王者要有装备,学编程要有设备,学习编程必备大礼包
    Java学习笔记:数据库中的范式和反范式的区别
    linux云计算主要就业岗位有哪些
    字典
    python统计字符串里每个字符的次数
    cf509B Painting Pebbles
    cf509A Maximum in Table
    bzoj1996 [Hnoi2010]chorus 合唱队
    bzoj3173 [Tjoi2013]最长上升子序列
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13472936.html
Copyright © 2020-2023  润新知