题目大意:定义一个序列为【不无聊的】当且仅当这个序列的任意一个区间都存在一个数只出现过一次,给定一个序列,要求判断这个序列是否是【不无聊的】
定义
我们可以将区间的左右端点放在二维平面上,那么一个元素产生的贡献是一个矩形,我们要确定的是所有元素对应的矩形的并集是否是覆盖所有合法区间对应的点
显然线段树+扫描线就行了
写完卡时过你告诉我正解是暴力?????
#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 线段树+扫描线
原文地址:http://blog.csdn.net/popoqqq/article/details/46380617