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

BZOJ 4059 Cerc2012 Non-boring sequences 线段树+扫描线

时间:2015-06-05 22:46:28      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj4059   线段树   扫描线   

题目大意:定义一个序列为【不无聊的】当且仅当这个序列的任意一个区间都存在一个数只出现过一次,给定一个序列,要求判断这个序列是否是【不无聊的】
定义lasti表示第i个元素上一次出现的位置(第一次出现则为0),nexti表示第i个元素下一次出现的位置(最后一次出现则为n+1),那么这个元素能成为某个区间仅出现一次的数,当且仅当这个区间的左端点在[lasti+1,i]之间,右端点在[i,nexti?1]之间
我们可以将区间的左右端点放在二维平面上,那么一个元素产生的贡献是一个矩形,我们要确定的是所有元素对应的矩形的并集是否是覆盖所有合法区间对应的点
显然线段树+扫描线就行了
写完卡时过你告诉我正解是暴力?????

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;

int T;
struct Segtree{
    Segtree *ls,*rs;
    int min_val,mark;
    void* operator new (size_t)
    {
        static Segtree mempool[M<<1],*C;
        static int tim;
        if(tim!=T)
            tim=T,C=mempool;
        C->ls=C->rs=0x0;
        C->min_val=C->mark=0;
        return C++;
    }
    void Add(int x)
    {
        min_val+=x;
        mark+=x;
    }
    void Push_Up()
    {
        min_val=min(ls->min_val,rs->min_val);
    }
    void Push_Down()
    {
        if(mark)
        {
            ls->Add(mark);
            rs->Add(mark);
            mark=0;
        }
    }
    void Build_Tree(int x,int y)
    {
        int mid=x+y>>1;
        if(x==y)
            return ;
        (ls=new Segtree)->Build_Tree(x,mid);
        (rs=new Segtree)->Build_Tree(mid+1,y);
    }
    void Modify(int x,int y,int l,int r,int val)
    {
        int mid=x+y>>1;
        if(x==l&&y==r)
        {
            Add(val);
            return ;
        }
        Push_Down();
        if(r<=mid)
            ls->Modify(x,mid,l,r,val);
        else if(l>mid)
            rs->Modify(mid+1,y,l,r,val);
        else
            ls->Modify(x,mid,l,mid,val) , rs->Modify(mid+1,y,mid+1,r,val) ;
        Push_Up();
    }
    int Get_Min(int x,int y,int l,int r)
    {
        int mid=x+y>>1;
        if(x==l&&y==r)
            return min_val;
        Push_Down();
        if(r<=mid)
            return ls->Get_Min(x,mid,l,r);
        if(l>mid)
            return rs->Get_Min(mid+1,y,l,r);
        return min( ls->Get_Min(x,mid,l,mid) , rs->Get_Min(mid+1,y,mid+1,r) ) ;
    }
}*tree;

struct abcd{
    int pos,l,r,type;
    bool operator < (const abcd &a) const
    {
        return pos < a.pos ;
    }
}stack[M<<1];
int n,top;
int a[M],last[M],next[M];
map<int,int> pos;

void Initialize()
{
    ++T;top=0;tree=new Segtree;
}

void Insert(int x1,int x2,int y1,int y2)
{
    stack[++top].pos=x1;
    stack[  top].l=y1;
    stack[  top].r=y2;
    stack[  top].type=1;
    stack[++top].pos=x2+1;
    stack[  top].l=y1;
    stack[  top].r=y2;
    stack[  top].type=-1;
}

int main()
{
    int T,i,j;
    for(cin>>T;T;T--)
    {
        Initialize();
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        pos.clear();
        for(i=1;i<=n;i++)
        {
            if(pos.find(a[i])==pos.end())
                last[i]=1;
            else
                last[i]=pos[a[i]]+1;
            pos[a[i]]=i;
        }
        pos.clear();
        for(i=n;i;i--)
        {
            if(pos.find(a[i])==pos.end())
                next[i]=n;
            else
                next[i]=pos[a[i]]-1;
            pos[a[i]]=i;
        }
        for(i=1;i<=n;i++)
            Insert(last[i],i,i,next[i]);

        sort(stack+1,stack+top+1);
        tree->Build_Tree(1,n);
        for(j=1,i=1;i<=n;i++)
        {
            for(;j<=top&&stack[j].pos==i;j++)
                tree->Modify(1,n,stack[j].l,stack[j].r,stack[j].type);
            if(tree->Get_Min(1,n,i,n)==0)
                break;
        }
        if(i==n+1)
            puts("non-boring");
        else
            puts("boring");
    }
    return 0;
}

BZOJ 4059 Cerc2012 Non-boring sequences 线段树+扫描线

标签:bzoj   bzoj4059   线段树   扫描线   

原文地址:http://blog.csdn.net/popoqqq/article/details/46380617

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