您的位置:首页 > 其它

[BZOJ3189][Coci2011][扫描线][线段树]Slika

2017-04-17 19:54 225 查看
首先发现LOAD和与其对应的SAVE之间的操作是没用的,所以可以O(m)扫两遍出去SAVE和LOAD操作。

对于这种矩形覆盖的问题,可以用扫面线加线段树处理。

开两棵线段树,用来记录(x+y)为奇数或偶数的时候被覆盖的情况,我们不妨扫描线扫x坐标,那么随着x+1,只要交换一下两颗线段树就可以了。

对于线段树中的一个结点,开一个set记录一下覆盖了这个结点表示的区间的颜色以及时间,以时间为关键字(我直接记录时间,在外面开个数组记录每个时间对应的颜色),这样就相当于区间覆盖,单点查询。

本地跑得贼慢,交到OJ上跑得比被抓的余畅还快

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#define N 1010
#define M 100010

using namespace std;

int n,m,k,t;
int S[M],cl[M];
char c
;
struct stp{
int op,x1,y1,x2,y2,c,t;
}A[M];
vector<stp> b
,e
;
struct seg{
int l,r;
set<int,greater<int> > S;
};

struct tree{
int L,R,Maxx;
seg T[2][N<<3];
tree(){ L=0; R=1; }
void Swap(){ swap(L,R); }
void insert(int g,int l,int r,int t,int p){
if(T[p][g].l==l&&T[p][g].r==r) return (void)T[p][g].S.insert(t);
int mid=T[p][g].l+T[p][g].r>>1;
if(r<=mid) insert(g<<1,l,r,t,p);
else if(l>mid) insert(g<<1|1,l,r,t,p);
else insert(g<<1,l,mid,t,p),insert(g<<1|1,mid+1,r,t,p);
}
void erase(int g,int l,int r,int x,int p){
if(T[p][g].l==l&&T[p][g].r==r) return (void)T[p][g].S.erase(x);
int mid=T[p][g].l+T[p][g].r>>1;
if(r<=mid) erase(g<<1,l,r,x,p);
else if(l>mid) erase(g<<1|1,l,r,x,p);
else erase(g<<1,l,mid,x,p),erase(g<<1|1,mid+1,r,x,p);
}
void erase(stp x){
if(((x.x2-x.x1+1)&1)^(x.y1&1))
erase(1,x.y1,x.y2,x.t,L);
else
erase(1,x.y1,x.y2,x.t,R);
}
void insert(stp x){
if(x.y1&1) insert(1,x.y1,x.y2,x.t,L);
else insert(1,x.y1,x.y2,x.t,R);
}
void query(int g,int x,int p){
if(!T[p][g].S.empty()) Maxx=max(Maxx,*T[p][g].S.begin());
if(T[p][g].l==T[p][g].r) return ;
int mid=T[p][g].l+T[p][g].r>>1;
if(x<=mid) query(g<<1,x,p);
else query(g<<1|1,x,p);
}
int query(int x){
Maxx=0; query(1,x,(x&1)?L:R);
return Maxx;
}
void Build(int g,int l,int r,int p){
T[p][g].l=l; T[p][g].r=r; T[p][g].S.clear();
if(l==r) return ;
int mid=l+r>>1;
Build(g<<1,l,mid,p); Build(g<<1|1,mid+1,r,p);
}
void build(){
Build(1,1,n,0); Build(1,1,n,1);
}
}T;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

inline void rea(char *x){
char c=nc(); int len=0;
for(;c>'Z'||c<'A';c=nc());for(;c>='A'&&c<='Z';x[len++]=c,c=nc());
}

int main(){
rea(n); rea(k); rea(m); cl[0]=1;
for(int i=1;i<=m;i++){
rea(c); A[i].t=i;
if(c[0]=='S') A[i].op=1;
else if(c[0]=='L') A[i].op=2,rea(A[i].c);
else{
rea(A[i].c),rea(A[i].x1),rea(A[i].y1),rea(A[i].x2),rea(A[i].y2);
A[i].x1++; A[i].x2++; A[i].y1++; A[i].y2++;
cl[i]=A[i].c;
}
}
for(int i=1;i<=m;i++) if(A[i].op==1) S[++t]=i;
/*for(int i=m;i>0;i--){
if(A[i].op==0) printf("%d %d\n",A[i].x1,A[i].x2);
else if(A[i].op==2) i=S[A[i].c];
}
return 0;*/
for(int i=m;i>0;i--){
if(A[i].op==0){
b[A[i].x1].push_back(A[i]);
e[A[i].x2+1].push_back(A[i]);
}
else if(A[i].op==2) i=S[A[i].c];
}
T.build();
for(int i=1;i<=n;i++,putchar('\n')){
T.Swap();
for(int j=0;j<e[i].size();j++)
T.erase(e[i][j]);
for(int j=0;j<b[i].size();j++)
T.insert(b[i][j]);
for(int j=1;j<=n;j++)
printf("%d ",cl[T.query(j)]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: